Last active
February 24, 2021 10:18
-
-
Save xmyqsh/7e1e4cdee4da81b4775c1d6a654df55e to your computer and use it in GitHub Desktop.
BFS计算邻接矩阵,DFS+回溯暴力搜索,可以状态caching进一步优化,状态定义:[源节点][长度为node数的01字符串表示结点的访问状态],但是,重叠子问题比较少,只能做到常数级别的优化,相应的,状态空间庞大,呈阶乘级别增长
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 题目描述: | |
给定一个 n * m 的迷宫 maze, 其中: | |
. 表示空地 | |
S 表示起点 | |
T 表示终点 | |
* 表示障碍物 | |
0~9 表示不同的宝物 | |
请问从起点开始, 在拿到所有宝物之后走到终点, 最少需要多少步? 如果无法拿到全部的宝物并走到终点, 返回 -1. | |
样例 | |
样例 1: | |
输入:["T1S.",".*0*","....","..*."] | |
输出:4 | |
解释:(0,2)->(1,2)->(0,2)->(0,1)->(0,0) | |
样例 2: | |
输入:["1*S.","..0.","T..."] | |
输出:6 | |
解释:(0,2)->(1,2)->(1,1)->(1,0)->(0,0)->(1,0)->(2,0) | |
注意事项 | |
n, m <= 50 | |
迷宫中的数字是连续的, 并且从 0 开始. 每个数字最多出现一次. | |
地图上除了障碍物以外的所有点都可以行走. | |
在收集完所有宝物之前, 终点可以被当做空地. | |
*/ | |
// O((k + 2)*m*n + k!): k为宝物数量 | |
#include <iostream> | |
#include <vector> | |
#include <queue> | |
#include <string> | |
#include <unordered_map> | |
#include <cassert> | |
using namespace std; | |
inline int pack(int x, int y) { | |
return ((x << 8) | y); | |
} | |
bool bfs(vector<vector<int> >& dists, unordered_map<int, int>& mp, | |
vector<vector<bool> >& visited, const vector<string>& maze, | |
int m, int n, int Sx, int Sy) { | |
for (int i = 0; i != m; ++i) fill(visited[i].begin(), visited[i].end(), false); | |
queue<pair<int, int> > q; | |
q.push({Sx, Sy}); | |
int SKey = mp[pack(Sx, Sy)]; | |
// check valid and calc dists | |
int cnt = 0, step = 0; | |
while (!q.empty()) { | |
int s = q.size(); | |
while (s--) { | |
auto C = q.front(); q.pop(); | |
int x = C.first, y = C.second; | |
if (x == -1 || y == -1 || x == m || y == n) continue; | |
if (maze[x][y] == '*') continue; | |
if (visited[x][y]) continue; | |
visited[x][y] = true; | |
int key = pack(x, y); | |
if (mp.count(key)) { | |
int TKey = mp[key]; | |
dists[SKey][TKey] = step; | |
if (++cnt == dists.size()) break; | |
} | |
q.push({x - 1, y}); | |
q.push({x + 1, y}); | |
q.push({x, y - 1}); | |
q.push({x, y + 1}); | |
} | |
++step; | |
} | |
return cnt == dists.size(); | |
} | |
int minSteps(const vector<vector<int> >& dists, vector<bool>& reached, int remain, int SKey, int TKey) { | |
if (SKey == TKey) { | |
assert(dists[SKey][TKey] == -1); | |
return remain == 0 ? 0 : INT_MAX; | |
} | |
int minStep = INT_MAX; | |
reached[SKey] = true; | |
for (int i = 0; i != dists[SKey].size(); ++i) { | |
if (reached[i]) continue; | |
int subStep = minSteps(dists, reached, remain - 1, i, TKey); | |
if (subStep == INT_MAX) continue; | |
minStep = min(minStep, dists[SKey][i] + subStep); | |
} | |
reached[SKey] = false; | |
return minStep; | |
} | |
int minSteps(vector<string>& maze) { | |
// Write your code here | |
int m = maze.size(), n = maze[0].size(); | |
int Sx, Sy, Tx, Ty, cnt = 0; | |
unordered_map<int, int> mp; | |
vector<pair<int, int> > digits; | |
for (int i = 0; i != m; ++i) { | |
for (int j = 0; j != n; ++j) { | |
if (isdigit(maze[i][j])) mp[pack(i, j)] = cnt++; | |
else if (maze[i][j] == 'S') { Sx = i; Sy = j; mp[pack(i, j)] = cnt++; } | |
else if (maze[i][j] == 'T') { Tx = i; Ty = j; mp[pack(i, j)] = cnt++; } | |
} | |
} | |
vector<vector<int> > dists(cnt, vector<int>(cnt, -1)); | |
vector<vector<bool> > visited(m, vector<bool>(n)); | |
if (!bfs(dists, mp, visited, maze, m, n, Sx, Sy)) return -1; | |
for (const auto& item : mp) { | |
int x = (item.first >> 8), y = (item.first & ((1 << 8) - 1)); | |
if (maze[x][y] == 'S' || maze[x][y] == 'T') continue; | |
bfs(dists, mp, visited, maze, m, n, x, y); | |
} | |
vector<bool> reached(cnt, false); | |
return minSteps(dists, reached, cnt - 1, mp[pack(Sx, Sy)], mp[pack(Tx, Ty)]); | |
} | |
int main() { | |
/* | |
vector<string> maze = | |
{"T1S.", | |
".*0*", | |
"....", | |
"..*."}; // ans: 4 | |
vector<string> maze = | |
{"1*S.", | |
"..0.", | |
"T..."}; // ans: 6 | |
*/ | |
vector<string> maze = // ans: 130 | |
{"..................................................", | |
"........*......*..............*..................*", | |
"....*.............................................", | |
"....................*......................*......", | |
"................................*.*...............", | |
"..................................................", | |
"..........*.......................................", | |
"...........*......................................", | |
"..................................................", | |
"...................*..............................", | |
"...................*..............................", | |
"...........1......................................", | |
".....*.....................................*......", | |
"...............S..................................", | |
"...............................*........*.........", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"..*...............................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
".............*...*.................*..............", | |
".....................*......................*.....", | |
".*....................................*...........", | |
".................*................................", | |
"..................*...............................", | |
"..................................................", | |
"...............*.......*..........................", | |
"..................................................", | |
"....................................*.............", | |
"..*..................*............................", | |
"..........*..................0....................", | |
".4*....................................2..........", | |
"..........................*.......................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"........................................*.........", | |
".......*..........................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
"..................................................", | |
".*...................................*............", | |
"................T............................3...."}; | |
cout << minSteps(maze) << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment