**链接 : ** Here!
**思路 : ** 两遍BFS, 第一次是从 'Y' 搜索, 搜到 '@' 就将其累加到一个数组中, 这里采用将二维坐标点映射成一维的点, 第二次从 'M' 搜索, 搜到 '@' 就将其累加到一个数组中, 最后扫描一遍地图, 将 $ans$ 更新为字符为 '@' 的累加值最小值. 最后答案就是 $ans * 11$
/*************************************************************************
> File Name: 2612-Find-a-way.cpp
> Author:
> Mail:
> Created Time: 2017年11月29日 星期三 20时02分14秒
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 300
const int INF = 0x3f3f3f;
int n, m;
int cnt[MAX_N * MAX_N] = {0}; // 相当于是个hash表, 将所有二维点映射进去
int vis[MAX_N][MAX_N];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
char G[MAX_N][MAX_N];
struct Point {
Point () {}
Point (int x, int y, int step) : x(x), y(y), step(step) {}
int x, y, step;
};
bool check(Point pt) {
return !(pt.x < 0 || pt.x >= n || pt.y < 0 || pt.y >= m || vis[pt.x][pt.y] || (G[pt.x][pt.y] == '#'));
}
void solve(Point st) {
queue<Point> que;
que.push(st);
vis[st.x][st.y] = 1;
while(!que.empty()) {
Point now = que.front();
que.pop();
for (int i = 0 ; i < 4 ; ++i) {
Point temp(now.x + dx[i], now.y + dy[i], now.step + 1);
if (!check(temp)) continue;
vis[temp.x][temp.y] = 1;
if (G[temp.x][temp.y] == '@') cnt[temp.x * m + temp.y] += temp.step;
que.push(temp);
}
}
}
int main() {
Point st, ed;
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = 0 ; i < n ; ++i) {
getchar();
scanf("%s", G[i]);
for (int j = 0 ; j < m ; ++j) {
if (G[i][j] == 'Y') st.x = i, st.y = j, st.step = 0;
if (G[i][j] == 'M') ed.x = i, ed.y = j, ed.step = 0;
}
}
solve(st);
memset(vis, 0, sizeof(vis));
solve(ed);
memset(vis, 0, sizeof(vis));
int ans = INF;
for (int i = 0 ; i < n ; ++i) {
for (int j = 0 ; j < m ; ++j) {
if (G[i][j] == '@' && cnt[i * m + j] != 0) {
ans = min(ans, cnt[i * m + j]);
}
}
}
printf("%d
", ans * 11);
memset(G, 0, sizeof(G));
memset(cnt, 0, sizeof(cnt));
}
return 0;
}