Skip to content

Commit 9ff360b

Browse files
improve the time performance of 1036
1 parent fa7a34f commit 9ff360b

File tree

5 files changed

+149
-53
lines changed

5 files changed

+149
-53
lines changed
Lines changed: 72 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,76 @@
11
class Solution {
2+
3+
private:
4+
using point_t = std::vector<int>;
5+
6+
static inline uint64_t hash(const point_t &p)
7+
{
8+
return p[0] * 1e6 + p[1];
9+
}
10+
211
public:
3-
bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target)
12+
bool isEscapePossible(vector<vector<int>>& blocked,
13+
vector<int>& source,
14+
vector<int>& target)
15+
{
16+
// blocked points set, uint64_t is selected since it is larger than 1e6*le6
17+
std::unordered_set<uint64_t> bps;
18+
19+
for (auto &x: blocked)
20+
bps.insert(hash(x));
21+
22+
auto e1 = enclose(source, bps, target);
23+
auto e2 = enclose(target, bps, source);
24+
25+
return !e1 && !e2;
26+
}
27+
28+
private:
29+
bool enclose(const point_t &s,
30+
const std::unordered_set<uint64_t> & b,
31+
const point_t &d)
32+
{
33+
int max_points = (1+b.size()-1) * b.size()/2;
34+
35+
std::deque<point_t> Q;
36+
Q.push_back(s);
37+
38+
std::unordered_set<uint64_t> visited;
39+
visited.insert(hash(s));
40+
41+
while (!Q.empty() && visited.size() <= max_points)
442
{
5-
if (blocked.size()<=1) return true;
6-
unordered_set<string>blocks;
7-
for (auto b:blocked)
8-
blocks.insert(to_string(b[0])+"#"+to_string(b[1]));
9-
10-
if (enclose(source,target,blocks) || enclose(target,source,blocks))
11-
return false;
12-
else
13-
return true;
43+
int &r = Q.front()[0];
44+
int &c = Q.front()[1];
45+
46+
static std::vector<std::pair<int, int>> ds
47+
{
48+
{0, 1}, {-1, 0}, {0, -1}, {1, 0}
49+
};
50+
51+
for (auto &dir: ds)
52+
{
53+
auto rr = r + dir.first;
54+
auto cc = c + dir.second;
55+
56+
std::vector<int> p{rr, cc};
57+
58+
if (rr < 0 || rr >= 1e6 || // out of bound
59+
cc < 0 || cc >= 1e6 || // out of bound
60+
visited.find(hash(p)) != visited.end()|| // visited
61+
b.find(hash(p)) != b.end() ) // blocked
62+
continue;
63+
64+
if (p == d) // reached out to destination
65+
return false;
66+
67+
Q.push_back(p);
68+
visited.insert(hash(p));
69+
}
70+
71+
Q.pop_front();
1472
}
15-
16-
bool enclose(vector<int>& source, vector<int>& target, unordered_set<string>& blocks)
17-
{
18-
auto dir = vector<pair<int,int>>({{1,0},{-1,0},{0,1},{0,-1}});
19-
queue<pair<int,int>>q;
20-
unordered_set<string>visited;
21-
22-
q.push({source[0],source[1]});
23-
visited.insert(to_string(source[0])+"#"+to_string(source[1]));
24-
25-
while (!q.empty() && visited.size()<=19900)
26-
{
27-
int x = q.front().first;
28-
int y = q.front().second;
29-
q.pop();
30-
31-
for (int k=0; k<4; k++)
32-
{
33-
int i = x+dir[k].first;
34-
int j = y+dir[k].second;
35-
36-
if (i<0||i>=1e6||j<0||j>=1e6)
37-
continue;
38-
if (i==target[0] && j==target[1])
39-
return false;
40-
41-
string encode = to_string(i)+"#"+to_string(j);
42-
if (blocks.find(encode)!=blocks.end())
43-
continue;
44-
if (visited.find(encode)!=visited.end())
45-
continue;
46-
47-
visited.insert(encode);
48-
q.push({i,j});
49-
}
50-
}
51-
52-
if (q.empty())
53-
return true;
54-
else
55-
return false;
56-
}
57-
};
73+
// no points left in queue, indicating this attempt is enclosed
74+
return Q.empty();
75+
}
76+
};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include "gtest/gtest.h"
2+
#include <climits>
3+
#include <algorithm>
4+
#include <vector>
5+
#include <unordered_set>
6+
#include <deque>
7+
using namespace std;
8+
9+
#include <BFS/1036.Escape-a-Large-Maze/1036.Escape-a-Large-Maze.cpp>
10+
11+
TEST(escape_a_large_maze_test, I)
12+
{
13+
std::vector<std::vector<int>> blocked {
14+
{0,1}, {1,0}
15+
};
16+
17+
std::vector<int> source {0, 0};
18+
std::vector<int> target {0, 2};
19+
20+
ASSERT_FALSE(Solution().isEscapePossible(blocked, source, target));
21+
}
22+
23+
TEST(escape_a_large_maze_test, II)
24+
{
25+
std::vector<std::vector<int>> blocked {};
26+
27+
std::vector<int> source {0, 0};
28+
std::vector<int> target {999999, 999999};
29+
30+
ASSERT_TRUE(Solution().isEscapePossible(blocked, source, target));
31+
}
32+
33+
TEST(escape_a_large_maze_test, III)
34+
{
35+
std::vector<std::vector<int>> blocked {
36+
{1,0}, {1,1}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7}, {1,8}, {1,9},
37+
{1,10}, {1,11}, {1,12}, {1,13}, {1,14}, {1,15}, {1,16}, {1,17}, {1,18},
38+
{1,19}, {1,20}, {1,21}, {1,22}, {1,23}, {1,24}, {1,25}, {1,26}, {1,27},
39+
{1,28}, {1,29}, {1,30}, {1,31}, {1,32}, {1,33}, {1,34}, {1,35}, {1,36},
40+
{1,37}, {1,38}, {1,39}, {1,40}, {1,41}, {1,42}, {1,43}, {1,44}, {1,45},
41+
{1,46}, {1,47}, {1,48}, {1,49}, {1,50}, {1,51}, {1,52}, {1,53}, {1,54},
42+
{1,55}, {1,56}, {1,57}, {1,58}, {1,59}, {1,60}, {1,61}, {1,62}, {1,63},
43+
{1,64}, {1,65}, {1,66}, {1,67}, {1,68}, {1,69}, {1,70}, {1,71}, {1,72},
44+
{1,73}, {1,74}, {1,75}, {1,76}, {1,77}, {1,78}, {1,79}, {1,80}, {1,81},
45+
{1,82}, {1,83}, {1,84}, {1,85}, {1,86}, {1,87}, {1,88}, {1,89}, {1,90},
46+
{1,91}, {1,92}, {1,93}, {1,94}, {1,95}, {1,96}, {1,97}, {1,98}, {1,99},
47+
{1,100}, {1,101}, {1,102}, {1,103}, {1,104}, {1,105}, {1,106}, {1,107},
48+
{1,108}, {1,109}, {1,110}, {1,111}, {1,112}, {1,113}, {1,114}, {1,115},
49+
{1,116}, {1,117}, {1,118}, {1,119}, {1,120}, {1,121}, {1,122}, {1,123},
50+
{1,124}, {1,125}, {1,126}, {1,127}, {1,128}, {1,129}, {1,130}, {1,131},
51+
{1,132}, {1,133}, {1,134}, {1,135}, {1,136}, {1,137}, {1,138}, {1,139},
52+
{1,140}, {1,141}, {1,142}, {1,143}, {1,144}, {1,145}, {1,146}, {1,147},
53+
{1,148}, {1,149}, {1,150}, {1,151}, {1,152}, {1,153}, {1,154}, {1,155},
54+
{1,156}, {1,157}, {1,158}, {1,159}, {1,160}, {1,161}, {1,162}, {1,163},
55+
{1,164}, {1,165}, {1,166}, {1,167}, {1,168}, {1,169}, {1,170}, {1,171},
56+
{1,172}, {1,173}, {1,174}, {1,175}, {1,176}, {1,177}, {1,178}, {1,179},
57+
{1,180}, {1,181}, {1,182}, {1,183}, {1,184}, {1,185}, {1,186}, {1,187},
58+
{1,188}, {1,189}, {1,190}, {1,191}, {1,192}, {1,193}, {1,194}, {1,195},
59+
{1,196}, {1,197}, {1,198}, {0,199}
60+
};
61+
62+
std::vector<int> source {0, 0};
63+
std::vector<int> target {999, 999};
64+
65+
ASSERT_FALSE(Solution().isEscapePossible(blocked, source, target));
66+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
set(BINARY escape_a_large_maze_1036_test)
2+
3+
add_executable(${BINARY} 1036.Escape-a-Large-Maze.t.cpp)
4+
5+
target_link_libraries(${BINARY} gtest_main)
6+
7+
include(GoogleTest)
8+
9+
gtest_discover_tests(${BINARY})

tests/BFS/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(1036.Escape-a-Large-Maze)

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ FetchContent_MakeAvailable(googletest)
99

1010
include(GoogleTest)
1111

12+
add_subdirectory(BFS)
1213
add_subdirectory(Dynamic_Programming)

0 commit comments

Comments
 (0)