http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1649
这道题目真的纠结很久了,从一开始的dfs做法到bfs。dfs做的到是顺利,但是zoj上过不了,hdoj上倒是过了,数据弱。
题意上理解也有问题,看到hdoj上的discuss版,是关于a的问题。确实,r有多个。但我看到很多做法是只确定一个r的值并且这种做法也ok.但这样应该不可以。
bfs做法有2种,一种是用数组模拟队列,第二种是直接队列做。我比较喜欢用队列,感觉直观很多。
C++里的队列基本做法:
queue用法
1. back 返回队列最后一个元素引用
2. empty 判断队列是否为空
3. front 获得队列最前面一个元素引用
4. push 在队列尾添加一个数据
5. pop 删除队列头的一个数据
6. size 队列中元素个数
本题适合用优先队列
Priority_queue 用法
Priority_queue<type>Q //创建一个类型为type的队列Q
Bool empty() //判空
push(t) // 将t压入队列
pop() // 非空情况下删除队列中优先级最高地情况
Top() // 返回队列中优先级最高的元素。
http://support.microsoft.com/kb/157622/zh-cn
发下dfs我写的,但bfs是参考别人的有两种:普通队列和优先队列。看到小媛的还是觉得她比较靠谱:把符合条件的r都压入队列。。。
#include <stdio.h> char a[210][210]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int N,M,flag,count,endx,endy; int main() { void dfs(int x,int y,int temp); int startx,starty; int i,j; while(scanf("%d%d",&N,&M)!=EOF) { count=9999; flag=0; for(i=0;i<N+2;i++) { a[i][0]='#'; a[i][M+1]='#'; } for(i=0;i<M+2;i++) { a[0][i]='#'; a[N+1][i]='#'; } for(i=1;i<=N;i++) { getchar(); for(j=1;j<=M;j++) { scanf("%c",&a[i][j]); if(a[i][j]=='a') { startx=i; starty=j; } if(a[i][j]=='r') { endx=i; endy=j; } } } a[startx][starty]='#'; dfs(startx,starty,0); if(flag) printf("%d\n",count); else printf("Poor ANGEL has to stay in the prison all his life.\n"); } return 0; } void dfs(int x,int y,int temp) { int i,temp_x,temp_y; if(x==endx&&y==endy)//问题出在这里,之前在dfs函数之前就把a[x][y]覆盖成了'#',所以改步永远都无法做到。 { flag=1; if(count>temp) count=temp; return; } for(i=0;i<4;i++) { temp_x=x+dir[i][0]; temp_y=y+dir[i][1]; if(a[temp_x][temp_y]!='#') { if(a[temp_x][temp_y]=='x') { a[temp_x][temp_y]='#'; dfs(temp_x,temp_y,temp+2); a[temp_x][temp_y]='x'; } else { a[temp_x][temp_y]='#'; dfs(temp_x,temp_y,temp+1); a[temp_x][temp_y]='.'; } } } }
bfs:
优先队列的:http://blog.csdn.net/zxy_snow/article/details/6176139
#include <cstdio> #include <cstdlib> #include <iostream> #include <string.h> #include <queue> #define MAX 201 using namespace std; typedef struct ANG { int t; int x,y; }ANG; char map[MAX][MAX]; int vis[MAX][MAX]; int n,m; int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; priority_queue<ANG> q; bool operator<(ANG a, ANG b)//优先队列 { return a.t > b.t; } int BFS() { ANG tmp; int i,a,b,aa,bb,t; while( !q.empty() ) { tmp = q.top(); q.pop(); a = tmp.x; b = tmp.y; t = tmp.t; for(i=0; i<4; i++) { aa = a + dir[i][0]; bb = b + dir[i][1]; if( aa >= 0 && aa < n && bb >=0 && b < m && map[aa][bb] != '#' && !vis[aa][bb] ) { vis[aa][bb] = 1; if( map[aa][bb] == 'a' ) return t+1; if( map[aa][bb] == '.' ) { tmp.t = t + 1; tmp.x = aa; tmp.y = bb; q.push(tmp); } if( map[aa][bb] == 'x') { tmp.t = t + 2; tmp.x = aa; tmp.y = bb; q.push(tmp); } } } } return -1; } int main() { int i,k,ans; ANG tmp; while(~scanf("%d%d",&n,&m)) { memset(map,0,sizeof(map)); for(i=0; i<n; i++) scanf("%s",map[i]); while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); for(i=0; i<n; i++) for(k=0; k<m; k++) if( map[i][k] == 'r' ) { map[i][k] = '.'; tmp.x = i; tmp.y = k; tmp.t = 0; q.push(tmp);//原来是这样的每次把符合条件的全部都入队... vis[i][k] = 1; } ans=BFS(); if(ans !=-1) printf("%d\n",ans); else printf("Poor ANGEL has to stay in the prison all his life.\n"); } return 0; }
不用优先队列的话,遇到'x'不能直接t+2压入队列。学习了STL里的队列和优先队列的做法^_^