ZOJ-1649 Rescue BFS (HDU 1242)
看题传送门:
ZOJ http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1649
HDU http://acm.hdu.edu.cn/showproblem.php?pid=1242
题目大意初始位置在r,要求到达a的地点,地图上"."通过需要1s,“x"代表守卫,通过耗时2s,“#”不能走。
BFS的应用。
BFS求最短路径的原理是每一次向外扩张一格,(就像树的层次遍历一样),生成的BFS树把同一步数放于同一层,故能保证最优解。
这题变形之处在于,迷宫上有守卫,打到守卫需要1s,才能进入守卫所在的格子。
故不能简单的BFS。
1.
我想到的方法是:
用一个数组记录当前到达的最小步数,如果走过一个格子,下一次走过的时间比较短,那么入队列,更新数组。否则跳过。
2.
看了别人的方法还有:
先在进入守卫所在的地方然后干掉守卫。
如果当前的格子是x则把步数+1,还有把x改为. 并重新入队列。
剩下的就是简单的BFS。
3.
优先队列。。。。Orz大牛。
把队列里面的各个点的步数从小到大,先到达目标的一定是最优的。。。。Orz
方法一:BFS+剪枝。
#include<cstdio> #include<queue> #include<cstring> using namespace std; const int MAXN=200+10; const int INF=999999; char maze[MAXN][MAXN]; int vis[MAXN][MAXN]; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; int N,M; struct site { int x,y; int step; site(int i,int j,int s){x=i;y=j;step=s;} site(){} }start,en; queue<site> q; void bfs() { q.push(start); int i; while(!q.empty()) { site cur=q.front(); //等下试试temp,而不是q.push(site(nx,ny)); q.pop(); for(i=0;i<4;i++) { int nx=cur.x+dx[i]; int ny=cur.y+dy[i]; int ns=cur.step; if( nx>=0 && ny >=0 && nx < N && ny < M && maze[nx][ny]!='#' ) { if(maze[nx][ny]=='a' && ns+1 < en.step ) { en.step=ns+1; continue; } if(maze[nx][ny]=='.'&& ns + 1 < vis[nx][ny] ) //剪枝 { vis[nx][ny]=ns+1; q.push(site(nx,ny,ns+1)); } if (maze[nx][ny]=='x' && ns + 2 < vis[nx][ny] ) { vis[nx][ny]=ns+2; q.push(site(nx,ny,ns+2)); } } } } } int main() { while(scanf("%d%d",&N,&M)!=EOF) { while(!q.empty()) q.pop(); getchar(); int i,j; for(i=0;i<N;i++) { for(j=0;j<M;j++) { scanf("%c",&maze[i][j]); if(maze[i][j]=='r') { start.x=i; start.y=j; start.step=0; } else if(maze[i][j]=='a') { en.x=i; en.y=j; en.step=INF; } vis[i][j]=INF; } getchar(); } bfs(); if(en.step==INF) printf("Poor ANGEL has to stay in the prison all his life.\n"); else printf("%d\n",en.step); } }
方法二:先干掉守卫
#include<cstdio> #include<queue> #include<cstring> using namespace std; const int MAXN=200+10; const int INF=999999; char maze[MAXN][MAXN]; bool vis[MAXN][MAXN]; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; int N,M; struct site { int x,y; int step; site(int i,int j,int s){x=i;y=j;step=s;} site(){} }start,en; queue<site> q; void bfs() { memset(vis,0,sizeof(vis)); q.push(start); int i; while(!q.empty()) { site cur=q.front(); q.pop(); if(maze[cur.x][cur.y]=='x') { maze[cur.x][cur.y]='.'; cur.step++; q.push(cur); continue; } for(i=0;i<4;i++) { int nx=cur.x+dx[i]; int ny=cur.y+dy[i]; int ns=cur.step; if( nx>=0 && ny >=0 && nx < N && ny < M && maze[nx][ny]!='#' &&!vis[nx][ny]) { if(maze[nx][ny]=='a' ) { en.step=ns+1; return; } //此时无需判断是否为x或者.,因为我们是先干掉守卫然后在进入守卫所在的地方。 q.push(site(nx,ny,ns+1)); vis[nx][ny]=true; } } } } int main() { while(scanf("%d%d",&N,&M)!=EOF) { while(!q.empty()) q.pop(); getchar(); int i,j; for(i=0;i<N;i++) { for(j=0;j<M;j++) { scanf("%c",&maze[i][j]); if(maze[i][j]=='r') { start.x=i; start.y=j; start.step=0; } else if(maze[i][j]=='a') { en.x=i; en.y=j; en.step=INF; } } getchar(); } bfs(); if(en.step==INF) printf("Poor ANGEL has to stay in the prison all his life.\n"); else printf("%d\n",en.step); } }
方法三: 优先队列
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN=200+10; const int INF=0x3ffffff; char map[MAXN][MAXN]; bool vis[MAXN][MAXN]; const int dx[]={1,-1,0,0}; const int dy[]={0,0,1,-1}; struct node { int step,x,y; node(){} node(int x,int y,int step): x(x),y(y),step(step){} bool operator < (const node&a)const{ return step>a.step; } }s,e; void bfs() { memset(vis,0,sizeof(vis)); priority_queue<node> q; q.push(s); vis[s.x][s.y]=true; while(!q.empty()) { node cur=q.top(); q.pop(); for(int i=0;i<4;i++) { int nx=cur.x+dx[i],ny=cur.y+dy[i]; if(map[nx][ny]=='a') { e.step=cur.step+1; return; } if(map[nx][ny]!='#'&&!vis[nx][ny]) { if(map[nx][ny]=='x') { q.push(node(nx,ny,cur.step+2)); map[nx][ny]='.'; vis[nx][ny]=true; } else { q.push(node(nx,ny,cur.step+1)); vis[nx][ny]=true; } } } } } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) { scanf("%s",map[i]+1); for(int j=1;j<=m;j++) { if(map[i][j]=='a') { e.x=i;e.y=j;e.step=INF; } if(map[i][j]=='r') { s.x=i;s.y=j;s.step=0; } } } for(int i=0;i<=m+1;i++) map[0][i]=map[n+1][i]='#'; for(int i=0;i<=n+1;i++) map[i][0]=map[i][m+1]='#'; /* for(int i=0;i<=n+1;i++) { for(int j=0;j<=m+1;j++) printf("%c",map[i][j]); printf("\n"); }*/ bfs(); if(e.step==INF) puts("Poor ANGEL has to stay in the prison all his life."); else printf("%d\n",e.step); } return 0; }
新 blog : www.hrwhisper.me