POJ 2312
坦克大战,童年回忆
这道题比较特殊的在于砖墙的出力,很明白的就可以想到距离变为2,然而这样在使用BFS寻求最短路径的时候违背了一个原则,算法导论上有这部分详细介绍,就是关于每时每刻队列内是一个单调不减的数列,此外,头和尾插值最大为1,一次推入一个距离为2的,会破坏BFS这些性质,所以想了一个这种的方法,即,不局限于二维,每次遇到砖块,先“跳到”高一维度,距离仅增加一,而同时在高一维度,只能跳回二维世界,这样强制增加一个额外经过的点,便可以解决这个问题
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;
const int maxw= 305;
char mz[maxw][maxw];
int vis[maxw][maxw], dis[maxw][maxw], bw[maxw][maxw];
int step[4][2]= {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int si, sj;
int BFS(int m, int n)
{
memset(vis, 0, sizeof(vis));
memset(bw, 0, sizeof(bw));
vis[si][sj]= 1;
dis[si][sj]= 0;
queue<pair<int, int> > Q;
Q.push(make_pair(si, sj));
int x, y, nx, ny;
int v;
while (!Q.empty()){
x= Q.front().first;
y= Q.front().second;
Q.pop();
v= dis[x][y]+1;
if (bw[x][y]){
dis[x][y]= v;
bw[x][y]= 0;
Q.push(make_pair(x, y));
continue;
}
for (int i= 0; i< 4; ++i){
nx= x+step[i][0];
ny= y+step[i][1];
if ('T'== mz[nx][ny]){
return v;
}
if (nx> 0 && nx<= m && ny> 0 && ny<= n && !vis[nx][ny]){
if ('E'== mz[nx][ny]){
vis[nx][ny]= 1;
dis[nx][ny]= v;
Q.push(make_pair(nx, ny));
}
else if ('B'== mz[nx][ny]){
bw[nx][ny]= 1;
vis[nx][ny]= 1;
dis[nx][ny]= v;
Q.push(make_pair(nx, ny));
}
}
}
}
return -1;
}
int main()
{
int m, n;
while (~scanf("%d %d", &m, &n) && m){
for (int i= 1; i<= m; ++i){
scanf("%s", mz[i]+1);
for (int j= 1; j<= n; ++j){
if ('Y'== mz[i][j]){
si= i;
sj= j;
}
}
}
printf("%d\n", BFS(m, n));
}
return 0;
}