kuangbin專題 簡單搜尋(bfs+dfs) 個人題解
阿新 • • 發佈:2019-02-02
VJ:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=80667#overview
出處:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65959#overview
越寫到後面越是順手,1次AC的越來越多,並且英文題目也讀的越來越順,算是一種進步吧。
A POJ 1321
窮舉組合數dfs暴力,注意一個點確定那麼那行那列就不能放
//組合數的回溯法 //用cstring或string.h 不要用memory.h #include<iostream> #include<cstring> using namespace std; const int maxn = 100; int n, k; int px[maxn], py[maxn]; int all; int ans; int visited[maxn]; int vx[9], vy[9]; void dfs(int num, int cur); int main() { ios::sync_with_stdio(false); while (cin >> n >> k) { if (n == -1 && k == -1)break; ans = 0; all = 0; memset(px, 0, sizeof(px)); memset(py, 0, sizeof(py)); memset(visited, 0, sizeof(visited)); char chTmp; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> chTmp; if (chTmp == '#') { px[all] = i; py[all] = j; all++; } } cin.ignore(); } dfs(0, 0); cout << ans << endl; } return 0; } void dfs(int num, int cur) { if (cur == k) { ans++; } else { for (int i = num; i < all; i++) { if (visited[i] == 0 && vx[px[i]] == 0 && vy[py[i]] == 0) { visited[i] = 1; vx[px[i]]++; vy[py[i]]++; dfs(i + 1, cur + 1); visited[i] = 0; vx[px[i]]--; vy[py[i]]--; } } } }
B POJ 2251
3DBFS,擴充套件而已。水題
#include<iostream> #include<string> #include<queue> #include<algorithm> using namespace std; int L, R, C; const int maxn = 32; struct Node { int l, r, c; int path; //-1 = # 1 = . 2 = E int own; void assign(int x, int y, int z) { l = x; r = y; c = z; path = -1; own = 0; } }node[maxn][maxn][maxn]; queue<Node> Q; int bfs() { Node temp; while (!Q.empty()) { temp = Q.front(); if (temp.own == 2)return temp.path; for (int dl = -1; dl < 2; dl++) for (int dr = -1; dr < 2; dr++) for (int dc = -1; dc < 2; dc++) { int a[3] = { dl, dr, dc }; sort(a, a + 3); if (!((a[0] == 0 && a[1] == 0) || (a[1] == 0 && a[2] == 0)))continue; if (temp.l + dl > 0 && temp.l + dl <= L && temp.r + dr > 0 && temp.r + dr <= R && temp.c + dc > 0 && temp.c + dc <= C && node[temp.l + dl][temp.r + dr][temp.c + dc].own > 0 && node[temp.l + dl][temp.r + dr][temp.c + dc].path < 0) { node[temp.l + dl][temp.r + dr][temp.c + dc].path = node[temp.l][temp.r][temp.c].path + 1; Q.push(node[temp.l + dl][temp.r + dr][temp.c + dc]); } } Q.pop(); } return 0; } int main() { ios::sync_with_stdio(false); while (cin >> L >> R >> C) { if (L == 0 && R == 0 && C == 0)break; while (!Q.empty())Q.pop(); string tmp; for (int i = 1; i <= L; i++) { for (int j = 1; j <= R; j++) { cin >> tmp; for (int k = 1; k <= C; k++) { node[i][j][k].assign(i, j, k); switch (tmp[k - 1]) { case '.':node[i][j][k].own = 1; break; case 'S':node[i][j][k].own = 1; node[i][j][k].path = 0; Q.push(node[i][j][k]); break; case 'E':node[i][j][k].own = 2; break; } } } } int ans = bfs(); if (ans == 0)cout << "Trapped!\n"; else cout << "Escaped in " << ans << " minute(s).\n"; } return 0; }
C POJ 3278
隱式bfs。水題
#include<iostream> #include<queue> #include<cstring> using namespace std; const int maxn = 100001; int N, K; queue<int> Q; int path[maxn]; int main() { cin >> N >> K; memset(path, -1, sizeof(path)); path[N] = 0; Q.push(N); int temp; while (!Q.empty()) { temp = Q.front(); Q.pop(); if (temp == K) { cout << path[temp] << endl; } if (temp > 0 && path[temp - 1] < 0) { Q.push(temp - 1); path[temp - 1] = path[temp] + 1; } if (temp < 100000 && path[temp + 1] < 0) { Q.push(temp + 1); path[temp + 1] = path[temp] + 1; } if (temp * 2 < maxn && path[temp * 2] < 0) { Q.push(temp * 2); path[temp * 2] = path[temp] + 1; } } return 0; }
D POJ 3279
值得注意的是第一行一旦確定後面行也確定。從這點出發的暴力運算量就可以AC
//顯然每個位置只能為0或1,不可能為2
//而當第一行一旦確定,後面的m-1行也就確定
//因此只要窮舉第一行的情況,1<<16的運算量,再選字典序最小即可
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int M, N;
int m[17][17];
int map[17][17];
int ans[17][17];
int minans[17][17];
int minp = (1 << 30);
int minv = (1 << 30);
const int dx[] = { 1, -1, 0, 0 };
const int dy[] = { 0, 0, 1, -1 };
void flip(int row, int col)
{
if (map[row][col] == 0)map[row][col] = 1;
else map[row][col] = 0;
for (int i = 0; i < 4; i++)
{
if (row + dx[i] < 0 || row + dx[i] > M - 1 || col + dy[i] < 0 || col + dy[i] > N - 1)continue;
if (map[row + dx[i]][col + dy[i]] == 0)map[row + dx[i]][col + dy[i]] = 1;
else map[row + dx[i]][col + dy[i]] = 0;
}
}
int main()
{
cin >> M >> N;
memset(m, -1, sizeof(m));
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
cin >> m[i][j];
}
bool fuck = false;
for (int i = 0; i < (1 << N); i++)
{
memset(ans, 0, sizeof(ans));
for (int x = 0; x < M; x++)
{
for (int y = 0; y < N; y++)
map[x][y] = m[x][y];
}
for (int j = 0; j < N; j++)
{
ans[0][j] = (i & (1 << j));
if (ans[0][j] > 0)
{
ans[0][j] = 1;
flip(0, j);
}
}
for (int j = 1; j < M; j++)
{
for (int k = 0; k < N; k++)
{
if (map[j - 1][k] == 1)
{
flip(j, k);
ans[j][k] = 1;
}
}
}
bool zz = true;
for (int j = 0; j < N; j++)
{
if (map[M - 1][j] == 1)
{
zz = false;
break;
}
}
if (zz)
{
fuck = true;
int p = 0;
for (int k = 0; k < M; k++)
for (int j = 0; j < N; j++)
{
p += ans[k][j];
}
if (p < minv || (p == minv && minp > i))
{
minv = p;
minp = i;
memcpy(minans, ans, sizeof(ans));
}
}
}
if (!fuck)cout << "IMPOSSIBLE\n";
else
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N - 1; j++)
{
cout << minans[i][j] << " ";
}
cout << minans[i][N - 1] << endl;
}
}
return 0;
}
E POJ 1426
隱式bfs剪枝,從最高位1開始。利用數論的知識來優化就不會爆炸
//第一位必定為1 選最小的即可
//從最高位開始向後bfs,補0或1
//剪枝:對於完全剩餘系0-n-1
//比如在第3位出現了k,而到第9位為0,結束
//那麼我在第6位又出現k,顯然到12位就會為0
//因此可以直接把又出現k的情況直接扔掉
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int N;
struct Node
{
int value;
int pos;
int store[205];
Node() {}
Node(int a) :pos(a), value(1) { memset(store, 0, sizeof(store)); store[a] = 1; }
Node(Node n, int p)
{
pos = n.pos + 1;
value = (n.value * 10 + p) % N;
memcpy(store, n.store, sizeof(store));
store[pos] = p;
}
void print()
{
for (int i = 1; i <= pos; i++)
{
cout << store[i];
}
cout << endl;
}
};
Node first;
queue<Node> Q;
int visited[205];
int main()
{
while (cin >> N && N > 0)
{
memset(visited, 0, sizeof(visited));
while (!Q.empty())
{
Q.pop();
}
first = Node(1);
Q.push(first);
while (!Q.empty())
{
first = Q.front();
Q.pop();
if (visited[first.value] == 1)continue;
else visited[first.value] = 1;
if (first.value == 0)
{
first.print();
break;
}
Q.push(Node(first, 0));
Q.push(Node(first, 1));
}
}
return 0;
}
F POJ 3126
注意素數的判別不要弄錯,小於等於根號n
//注意判斷素數那裡小於等於根號i
#include<iostream>
#include<set>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
int M;
bool prime[10005];
int path[10005];
queue<int> Q;
void primebuild()
{
memset(prime, 0, sizeof(prime));
for (int i = 1001; i < 10000; i++)
{
int temp = floor(sqrt(1.0*i) + 0.5);
bool fuck = true;
for (int j = 2; j <= temp; j++)
{
if (i % j == 0)
{
fuck = false;
break;
}
}
prime[i] = fuck;
}
}
int bfs(int a, int b)
{
memset(path, -1, sizeof(path));
while (!Q.empty())
{
Q.pop();
}
path[a] = 0;
Q.push(a);
int first;
while (!Q.empty())
{
first = Q.front();
Q.pop();
if (first == b)return path[first];
int p = first % 1000;
for (int i = 1; i < 10; i++)
{
p += 1000;
if (path[p] < 0 && prime[p])
{
Q.push(p);
path[p] = path[first] + 1;
}
}
p = (first / 1000) * 1000 + (first % 100);
for (int i = 0; i < 10; i++)
{
if (path[p] < 0 && prime[p])
{
Q.push(p);
path[p] = path[first] + 1;
}
p += 100;
}
p = first - (first % 100) + (first % 10);
for (int i = 0; i < 10; i++)
{
if (path[p] < 0 && prime[p])
{
Q.push(p);
path[p] = path[first] + 1;
}
p += 10;
}
p = first - (first % 10);
for (int i = 0; i < 10; i++)
{
if (path[p] < 0 && prime[p])
{
Q.push(p);
path[p] = path[first] + 1;
}
p++;
}
}
return -1;
}
int main()
{
primebuild();
cin >> M;
while (M--)
{
int a, b;
cin >> a >> b;
cout << bfs(a, b) << endl;
}
return 0;
}
G POJ 3087
模擬題,注意某一狀態第二次出現時剪枝。水題
//純模擬題,注意兩副牌重複交叉一定次數一定會迴圈到開始
#include<iostream>
#include<cstring>
#include<string>
#include<map>
using namespace std;
int M, C;
string a, b, c;
map<string, int> mm;
string change()
{
string ret = "";
for (int i = 0; i < (C << 1); i++)
{
if (i & 1) ret += a[i>>1];
else ret += b[i>>1];
}
a = ret.substr(0, C);
b = ret.substr(C, C);
return ret;
}
int main()
{
cin >> M;
for (int kase = 0; kase < M; kase++)
{
mm.clear();
cin >> C >> a >> b >> c;
cout << kase + 1 << " ";
int ans = 0;
while (true)
{
string temp = change();
ans++;
if (temp == c)break;
else
{
if (mm[temp] == 1)
{
ans = -1;
break;
}
else
{
mm[temp] = 1;
}
}
}
cout << ans << endl;
}
return 0;
}
H POJ 3414
細節上別弄錯。bfs水題
//類的建構函式的形參型別為該類必須用引用
//注意set放結構體的時候必須要過載<
#include<iostream>
#include<queue>
#include<set>
#include<string>
using namespace std;
int a, b, c;
struct State
{
int la, lb;
bool ok() { if (la == c || lb == c)return true; return false; }
int path;
string way;
State() :path(-1), la(0), lb(0), way("") {}
};
struct Node
{
int la, lb;
Node(State a):la(a.la), lb(a.lb) {}
};
bool operator < (Node a, Node b)
{
if (a.la != b.la)return a.la < b.la;
else return a.lb < b.lb;
}
set<Node> S;
queue<State> Q;
int main()
{
cin >> a >> b >> c;
State first;
first.path++;
Q.push(first);
bool fuck = false;
while (!Q.empty())
{
first = Q.front();
Q.pop();
Node node(first);
if (S.count(node))continue;
else S.insert(node);
if (first.ok())
{
cout << first.path << endl;
cout << first.way;
fuck = true;
break;
}
else
{
first.path++;
State temp = first;
if (first.la < a)
{
temp.way += "FILL(1)\n";
temp.la = a;
Q.push(temp);
}
temp = first;
if (first.lb < b)
{
temp.way += "FILL(2)\n";
temp.lb = b;
Q.push(temp);
}
temp = first;
if (first.la > 0)
{
temp.way += "DROP(1)\n";
temp.la = 0;
Q.push(temp);
}
temp = first;
if (first.lb > 0)
{
temp.way += "DROP(2)\n";
temp.lb = 0;
Q.push(temp);
}
temp = first;
if (first.la < a && first.lb > 0)
{
temp.way += "POUR(2,1)\n";
int cc = a - first.la;
if (cc > first.lb)
{
temp.la += first.lb;
temp.lb = 0;
}
else
{
temp.lb -= cc;
temp.la = a;
}
Q.push(temp);
}
temp = first;
if (first.lb < b && first.la > 0)
{
temp.way += "POUR(1,2)\n";
int cc = b - first.lb;
if (cc > first.la)
{
temp.lb += first.la;
temp.la = 0;
}
else
{
temp.la -= cc;
temp.lb = b;
}
Q.push(temp);
}
}
}
if (!fuck) cout << "impossible" << endl;
return 0;
}
I FZU 2150
dfs窮舉組合數+bfs。注意筆誤
//dfs窮舉組合數+bfs暴力
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;
int map[12][12];
int grass[12][12];
int T, n, m;
int px[105], py[105];
int tot;
int fire[3];
int ans;
int dx[] = { -1, 0, 1, 0 };
int dy[] = { 0, 1, 0, -1 };
int visited[12][12];
struct Node
{
int x, y;
int path;
Node() {}
Node(int x, int y, int path) :x(x), y(y), path(path) {}
};
queue<Node> Q;
void dfs(int cur, int num)
{
if (cur == 2)
{
memcpy(grass, map, sizeof(map));
memset(visited, 0, sizeof(visited));
int t = -1;
Node t1 = Node(px[fire[0]], py[fire[0]], 0), t2 = Node(px[fire[1]], py[fire[1]], 0);
Q.push(t1);
Q.push(t2);
while (!Q.empty())
{
Node temp = Q.front();
Q.pop();
if (grass[temp.x][temp.y] == 0)continue;
else
{
t = max(t, temp.path);
grass[temp.x][temp.y] = 0;
for (int i = 0; i < 4; i++)
{
if (temp.x + dx[i] < 0 || temp.x + dx[i] > n - 1)continue;
if (temp.y + dy[i] < 0 || temp.y + dy[i] > m - 1)continue;
if (visited[temp.x + dx[i]][temp.y + dy[i]] == 1)continue;
Q.push(Node(temp.x + dx[i], temp.y + dy[i], temp.path + 1));
visited[temp.x + dx[i]][temp.y + dy[i]] = 1;
}
}
}
bool fuck = true;
for (int i = 0; i < n; i++)
{
bool cc = true;
for (int j = 0; j < m; j++)
{
if (grass[i][j] == 1)
{
cc = false;
break;
}
}
if (!cc)
{
fuck = false;
break;
}
}
if (fuck)
{
ans = min(ans, t);
}
}
else
{
for (int i = num; i < tot; i++)
{
fire[cur] = i;
dfs(cur + 1, i);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> T;
for (int kase = 0; kase < T; kase++)
{
tot = 0;
ans = (1 << 30);
memset(map, 0, sizeof(map));
memset(px, -1, sizeof(px));
memset(py, -1, sizeof(py));
cin >> n >> m;
char chTmp;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> chTmp;
if (chTmp == '#')
{
map[i][j] = 1;
px[tot] = i;
py[tot] = j;
tot++;
}
else
map[i][j] = 0;
}
cin.ignore();
}
dfs(0, 0);
if (ans == (1 << 30))ans = -1;
cout << "Case " << kase + 1 << ": " << ans << endl;
}
return 0;
}
J UVA 11624
注意狀態的先後變化。bfs水題
#include<iostream>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
int T;
int R, C;
int fr, fc;
int map[1005][1005];
int visited[1005][1005];
const int dr[] = { 0, 1, 0, -1 };
const int dc[] = { 1, 0, -1, 0 };
struct Node
{
int row, col;
int path;
bool fire;
Node() {}
Node(int row, int col, int path, bool fire) :row(row), col(col), path(path), fire(fire) {}
};
queue<Node> Q;
int main()
{
cin >> T;
while (T--)
{
while (!Q.empty())
{
Q.pop();
}
memset(map, -1, sizeof(map));
memset(visited, 0, sizeof(visited));
cin >> R >> C;
char chTmp;
for (int i = 1; i <= R; i++)
{
for (int j = 1; j <= C; j++)
{
cin >> chTmp;
if (chTmp == '#')
{
map[i][j] = -1;
}
else
{
if (chTmp == '.')
{
map[i][j] = 1;
}
else
{
if (chTmp == 'F')
{
map[i][j] = -2;
Q.push(Node(i, j, -1, true));
}
else
{
map[i][j] = 1;
fr = i;
fc = j;
}
}
}
}
cin.ignore();
}
Q.push(Node(fr, fc, 0, false));
bool fuck = true;
Node first;
while (!Q.empty())
{
first = Q.front();
Q.pop();
if (!first.fire)
{
for (int i = 0; i < 4; i++)
{
if (first.row + dr[i] < 1 || first.row + dr[i] > R || first.col + dc[i] < 1 || first.col + dc[i] > C)
{
fuck = false;
cout << first.path + 1 << endl;
break;
}
else
{
if (visited[first.row + dr[i]][first.col + dc[i]] == 0 && map[first.row + dr[i]][first.col + dc[i]] > 0)
{
visited[first.row + dr[i]][first.col + dc[i]] = 1;
Q.push(Node(first.row + dr[i], first.col + dc[i], first.path + 1, false));
}
}
}
if (!fuck)break;
}
else
{
for (int i = 0; i < 4; i++)
{
if (first.row + dr[i] < 1 || first.row + dr[i] > R || first.col + dc[i] < 1 || first.col + dc[i] > C)continue;
if (map[first.row + dr[i]][first.col + dc[i]] > 0 && visited[first.row + dr[i]][first.col + dc[i]] == 0)
{
Q.push(Node(first.row + dr[i], first.col + dc[i], -1, true));
map[first.row + dr[i]][first.col + dc[i]] = -2;
visited[first.row + dr[i]][first.col + dc[i]] = 1;
}
}
}
}
if (fuck)cout << "IMPOSSIBLE" << endl;
}
return 0;
}
K POJ 3984
本專題最簡單的水題。
#include<iostream>
#include<string>
#include<queue>
using namespace std;
int map[5][5];
int visited[5][5];
const int dr[] = { -1, 0, 1, 0 };
const int dc[] = { 0, -1, 0, 1 };
struct Node
{
int row, col;
int path;
string way;
Node(int row, int col, int path) :row(row), col(col), path(path) { way = ""; }
};
queue<Node> Q;
int main()
{
for (int i = 0; i < 5; i++)
for (int j = 0; j < 5; j++)
cin >> map[i][j];
Node first = Node(0, 0, 0);
first.way = "(0, 0)\n";
visited[0][0] = 1;
Q.push(first);
while (!Q.empty())
{
first = Q.front(); Q.pop();
if (first.row == 4 && first.col == 4)
{
cout << first.way;
break;
}
else
{
for (int i = 0; i < 4; i++)
{
if (first.row + dr[i] < 0 || first.row + dr[i] > 4 || first.col + dc[i] < 0 || first.col + dc[i] > 4)
{
continue;
}
else
{
if (map[first.row + dr[i]][first.col + dc[i]] == 0 && visited[first.row + dr[i]][first.col + dc[i]] == 0)
{
Node temp = first;
temp.row += dr[i];
temp.col += dc[i];
temp.path++;
temp.way += "(";
temp.way += first.row + dr[i] + 48;
temp.way += ", ";
temp.way += first.col + dc[i] + 48;
temp.way += ")\n";
Q.push(temp);
visited[first.row + dr[i]][first.col + dc[i]] = 1;
}
}
}
}
}
return 0;
}
L HDU 1241
紫書例題,八連通圖。水題
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 105;
const int dr[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dc[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int ans;
int r, c;
int map[maxn][maxn];
int visited[maxn][maxn];
void dfs(int row, int col);
int main()
{
char chTmp;
while (cin >> r >> c)
{
if (r == 0)break;
ans = 0;
memset(map, 0, sizeof(map));
memset(visited, 0, sizeof(map));
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> chTmp;
if (chTmp == '@')
map[i][j] = 1;
}
cin.ignore();
}
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
if (map[i][j] == 1 && visited[i][j] == 0)
{
dfs(i, j);
ans++;
}
}
}
cout << ans << endl;
}
return 0;
}
void dfs(int row, int col)
{
visited[row][col] = 1;
for (int i = 0; i < 8; i++)
{
if (row + dr[i] < 1 || row + dr[i] > r || col + dc[i] < 1 || col + dc[i] > c)continue;
if (map[row + dr[i]][col + dc[i]] == 1 && visited[row + dr[i]][col + dc[i]] == 0)
{
dfs(row + dr[i], col + dc[i]);
}
}
}
M HDU 1495
和上面某題極其相似。水題。
#include<iostream>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;
int s, n, m;
struct Node
{
int a, b, c;
int path;
Node(int a, int b, int c, int path) :a(a), b(b), c(c), path(path) {}
};
struct State
{
int a, b, c;
State() {}
State(Node x) :a(x.a), b(x.b), c(x.c) {}
};
bool operator < (const State& x, const State& y)
{
if (x.a != y.a) return x.a < y.a;
else
{
if (x.b != y.b) return x.b < y.b;
else return x.c < y.c;
}
}
set<State> S;
queue<Node> Q;
int main()
{
while (cin >> s >> n >> m)
{
while (!Q.empty())
{
Q.pop();
}
S.clear();
if (s == 0)break;
Node first = Node(s, 0, 0, 0);
State temp;
Q.push(first);
bool fuck = true;
if (s % 2 == 0)
while (!Q.empty())
{
first = Q.front(); Q.pop();
temp = State(first);
int pp[3] = { first.a, first.b, first.c };
sort(pp, pp + 3);
if (pp[1] == s / 2 && pp[2] == s / 2)
{
cout << first.path << endl;
fuck = false;
break;
}
if (S.count(temp) == 1)
{
continue;
}
else
{
S.insert(temp);
if (first.a > 0)
{
if (first.b < n)
{
Q.push(Node(max(0, first.a - n + first.b), min(n, first.b + first.a), first.c, first.path + 1));
}
if (first.c < n)
{
Q.push(Node(max(0, first.a - m + first.c), first.b, min(m, first.c + first.a), first.path + 1));
}
}
if (first.b > 0)
{
Q.push(Node(first.a + first.b, 0, first.c, first.path + 1));
if (first.c < m)
{
Q.push(Node(first.a, max(0, first.b - m + first.c), min(m, first.c + first.b), first.path + 1));
}
}
if (first.c > 0)
{
Q.push(Node(first.a + first.c, first.b, 0, first.path + 1));
if (first.b < m)
{
Q.push(Node(first.a, min(n, first.b + first.c), max(0, first.c - n + first.b), first.path + 1));
}
}
}
}
if (fuck)cout << "NO" << endl;
}
return 0;
}
N HDU 2612
注意不能用太暴力的方法,不然會MLE/TLE
//一開始的思路是窮舉每個點到Y M的距離, TLE
//改進了一下,打表,兩次BFS求Y\M到每個點的距離,AC
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 205;
const int dr[] = { -1, 0, 1, 0 };
const int dc[] = { 0, -1, 0, 1 };
int r, c;
int map[maxn][maxn];
int visited[maxn][maxn];
int tot = 0;
int kr[maxn*maxn], kc[maxn*maxn];
int yr, yc, mr, mc;
int yk[maxn*maxn], mk[maxn*maxn];
struct Node
{
int row, col;
int path;
Node() {}
Node(int row, int col, int path) :row(row), col(col), path(path) {}
};
queue<Node> Q;
int main()
{
char chTmp;
while (scanf("%d %d\n", &r, &c) != EOF)
{
memset(map, -1, sizeof(map));
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> chTmp;
if (chTmp == '.')
{
map[i][j] = 0;
}
else
{
if (chTmp == '@')
{
map[i][j] = ++tot;
kr[tot] = i;
kc[tot] = j;
}
else
{
if (chTmp == 'Y')
{
map[i][j] = 0;
yr = i;
yc = j;
}
else
{
if (chTmp == 'M')
{
map[i][j] = 0;
mr = i;
mc = j;
}
}
}
}
}
getchar();
}
Node temp;
memset(visited, 0, sizeof(visited));
memset(yk, -1, sizeof(yk));
Q.push(Node(yr, yc, 0));
visited[yr][yc] = 1;
while (!Q.empty())
{
temp = Q.front(); Q.pop();
if (map[temp.row][temp.col] > 0)
{
yk[map[temp.row][temp.col]] = temp.path;
}
for (int i = 0; i < 4; i++)
{
if (temp.row + dr[i] < 1 || temp.row + dr[i] > r || temp.col + dc[i] < 1 || temp.col + dc[i] > c)continue;
if (visited[temp.row + dr[i]][temp.col + dc[i]] == 0 && map[temp.row + dr[i]][temp.col + dc[i]] >= 0)
{
visited[temp.row + dr[i]][temp.col + dc[i]] = 1;
Q.push(Node(temp.row + dr[i], temp.col + dc[i], temp.path + 1));
}
}
}
memset(visited, 0, sizeof(visited));
memset(mk, -1, sizeof(mk));
Q.push(Node(mr, mc, 0));
visited[mr][mc] = 1;
while (!Q.empty())
{
temp = Q.front(); Q.pop();
if (map[temp.row][temp.col] > 0)
{
mk[map[temp.row][temp.col]] = temp.path;
}
for (int i = 0; i < 4; i++)
{
if (temp.row + dr[i] < 1 || temp.row + dr[i] > r || temp.col + dc[i] < 1 || temp.col + dc[i] > c)continue;
if (visited[temp.row + dr[i]][temp.col + dc[i]] == 0 && map[temp.row + dr[i]][temp.col + dc[i]] >= 0)
{
visited[temp.row + dr[i]][temp.col + dc[i]] = 1;
Q.push(Node(temp.row + dr[i], temp.col + dc[i], temp.path + 1));
}
}
}
int ans = (1 << 30);
for (int i = 1; i <= tot; i++)
{
if (yk[i] == -1 || mk[i] == -1)continue;
ans = min(ans, yk[i] + mk[i]);
}
printf("%d\n", ans * 11);
}
return 0;
}