2009
11.07
11.07
http://acm.pku.edu.cn/JudgeOnline/problem?id=2157
这应该是我做过的较为复杂的搜索题了!
首先,对输入的数据进行处理,记录下每个门的位置,以及每个门各需要多少钥匙才能打开!
于是钥匙数据有两个变量:对应的门的钥匙数量,目前拿到的钥匙的数量(当这两个变量相等的时候,才可将对应的门打开!)
门的数组有有三个变量,x,y,open。x和y是记录该门的位置,而open则是判断是否在搜索的过程中到达这个门。
只有当open==true,还有钥匙的数量等于目前那道该种钥匙的数量时,该门才能作为新的起点进行新一轮的遍历!
切记,门是走不过去的,也就是遇到门的时候要将其标记为普通点,否则下次将该点作为起点进行遍历的时候会重复走。接着就returne 0.这个问题导致了2次TLE。
而钥匙的点作为普通的点就行了。
为了方便处理,将起点作为第五个门,呵呵,的确是方便了很多!
当门数组从头到位走一次,都没发现可以作为新起点的门的时候,说明此迷宫是拿不到宝藏的,输出NO。
That ’s all!
其实代码并不长,只是判断语句太多了!
乱码如下:
#include<stdio.h> #include<string.h> struct keys { int total; int have; }key[8]; struct point { bool open; int x,y; }list[8]; int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; char g[21][21]; bool u[21][21],find; int n,m; int dfs(int x,int y) { if(g[x][y]=='X') return 0; else if(g[x][y]=='G') { find=true; return 0; } else if(g[x][y]>='A' && g[x][y]<='E') { list[g[x][y]-'A'].open=true; g[x][y]='.'; return 0; } else if(g[x][y]>='a' && g[x][y]<='e') { key[g[x][y]-'a'].have++; } int i,j,k,a,b; for(i=0;i<4;i++) { a=x+dir[i][0]; b=y+dir[i][1]; if(a>=0 && a<n && b>=0 && b<m && u[a][b]) { u[a][b]=false; dfs(a,b); if(find) return 0; } } } int main() { // freopen("1.txt","r",stdin); int i,j,k; while(scanf("%d %d",&n,&m)!=EOF) { find=false; memset(key,0,sizeof(key)); memset(list,0,sizeof(list)); memset(u,true,sizeof(u)); if(n==0 && m==0) return 0; for(i=0;i<n;i++) scanf("%s",g[i]); for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(g[i][j]=='.' || g[i][j]=='X') continue; else if(g[i][j]>='a' && g[i][j]<='e') { key[g[i][j]-'a'].total++; } else if(g[i][j]>='A' && g[i][j]<='E') { list[g[i][j]-'A'].x=i; list[g[i][j]-'A'].y=j; list[g[i][j]-'A'].open=false; } else if(g[i][j]=='S') { list[5].x=i; list[5].y=j; list[5].open=true; } } } while(1) { k=0; for(i=0;i<6;i++) { if(list[i].open && key[i].total==key[i].have) { k++; list[i].open=false; dfs(list[i].x,list[i].y); } if(find) { printf("YES\n"); break; } } if(find) break; if(k==0) { printf("NO\n"); break; } } } return 0; } |
暂无回复
添加回复