链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649
题意:有N行,M列的格子,从”r”出发,要到达“a”处,”#”不能走,走”x"要多用一个单位时间,“."用正常的单位时间。求最短时间。
思路:由于要求的是最短的时间,所以用广搜,但是最一般的广搜求出来的是最少的步数,此题要求的是最少的时间。在这个问题中,最少的步数并不代表时间也是最少的,因为可能会有很多的”x“出现,这样时间就长了。用一个结构体来表示当前位置的状态,包括走过的步数和所用的时间。数组mintime[x][y]表示走到(x,y)所花的最少时间,在搜索过程中,从当前位置到相邻的位置(x,y)时,只有当现在这种走法比以前的走法用的时间少,才把当前走到(x,y)位置所表示的状态入队。还有就是必须要等队列空了搜索过程才算结束,因为如果到了目的地搜索就结束的话,得到的是最少步数中的最短时间,并不一定是所求的解。因为入队时是只有当当前走法所花时间更少时才入队,而这个时间有下界,所以不会无限搜索下去。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn=202; const int INF=1000000; int dir[4][2]= {{-1,0},{0,1},{1,0},{0,-1}}; struct point { int x,y; int step; int time; }; queue<point> q; int N,M; char map[maxn][maxn]; int mintime[maxn][maxn]; int ax,ay; void bfs(point p) { q.push(p); point hd; while(!q.empty()) { hd=q.front(); q.pop(); for(int i=0; i<4; i++) { int x=hd.x+dir[i][0],y=hd.y+dir[i][1]; if(x<0 || y<0 || x>=N || y>=M) continue; if(map[x][y]=='#') continue; point t; t.x=x; t.y=y; t.step=hd.step+1; t.time=hd.time+1; if(map[x][y]=='x') t.time++; if(t.time<mintime[x][y]) { mintime[x][y]=t.time; q.push(t); } } } } int main() { int sx,sy; point start; while(~scanf("%d%d",&N,&M)) { getchar(); for(int i=0;i<N;++i) { for(int j=0;j<M;++j) { scanf("%c",&map[i][j]); mintime[i][j]=INF; if(map[i][j]=='a') { ax=i; ay=j; } else if(map[i][j]=='r') { sx=i; sy=j; } } getchar(); } start.x=sx; start.y=sy; start.step=0; start.time=0; mintime[sx][sy]=0; bfs(start); if(mintime[ax][ay]<INF) printf("%d\n",mintime[ax][ay]); else printf("Poor ANGEL has to stay in the prison all his life.\n"); } return 0; }
写完代码后就运行,把网上的输入复制了过来,结果一输入就异常退出,以为是代码有问题,检查了好久,还是没发现问题。然后把代码一段的一段的改得和书上的一样,才发现是输入有问题,用书上的写法就是对的,但是明明这么写也是可以的,非常奇怪。于是干脆交了,发现过了,深感郁闷。然后把那个输入复制到文本文件中观察了下,发现每行后面多复制了一个空格。。。。泪,内伤啊。
所以保险起见,以后还是按书上的那样写吧。
while()循环中
for(int i=0;i<N;i++) scanf("%s",map[i]); for(int i=0;i<N;++i) { for(int j=0;j<M;++j) { mintime[i][j]=INF; if(map[i][j]=='a') { ax=i; ay=j; } else if(map[i][j]=='r') { sx=i; sy=j; } } }
总之,不爽不爽不爽。