http://acm.hdu.edu.cn/showproblem.php?pid=3912
这个题我用递归深搜模拟,直接爆栈了。哭啊!为什么!
这个题最主要是能走重复格子,但是方向不一样。
我用的剪枝条件:
1、判断有没有走出迷宫,走出迷宫了直接退出。
2、由于题目要求只要判断有没有把所有格子走完,则可以用一个计数器统计走过格子的数量(重复走的不算)。走完了所有格子则直接退出搜索。
3、在这个格子,当前走的方向以前走过,则重复了(判重)
别人的代码贴在最后面吧。。
我自己爆栈的代码
:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int r,c,enty,exitx,exity; int yn,sum; //yn用于标记是否走出迷宫,sum记录走过几个格子 int map[510][510][5]; //地图,最后一个代表这个格子的边缘是否有墙,map[i][j][]代表ij这个格子的上下左右是否有墙 int dis[510][510][5]; //标记 struct Node { int x,y; //当前坐标位置 int fx; //当前前进方向,1下,2上,3左,4右 }p; void init() { int i,j,k,q; for(i = 0; i < 510; i++) //初始化全为墙 { for(j = 0; j < 510; j++) { map[i][j][0]=map[i][j][1]=map[i][j][2]=map[i][j][3]=map[i][j][4] = 1; } } memset(dis,0,sizeof(dis)); //初始标记,均没有走过 scanf("%d%d%d%d",&r,&c,&enty,&exity); exitx = r-1; p.x = 0; p.y = enty; p.fx = 1; //p把入口位置和方向保存 q = 0; for(i = 0; i < 2*r-1; i++) //更新边缘是否有墙 { if(i&1) { for(j = 0; j < c; j++) { scanf("%d",&k); map[q][j][1] = k; //格子上边 map[q+1][j][2] = k; //格子下边 } q++; } else { for(j = 0; j < c-1; j++) { scanf("%d",&k); map[q][j][4] = k; //格子的右边 map[q][j+1][3] = k; //格子的左边 } } } return ; } void right(Node now) { void Dfs(Node now); Node next; switch(now.fx) { case 1: { if(map[now.x][now.y][3]==0) //向下右转则向左,如果没有墙则能走 { next.x = now.x; next.y = now.y-1; next.fx = 3; //更改当先方向 if(dis[next.x][next.y][0]==0) //查看下一个格子以前走过没 { sum++; //没走过,增加一个 } Dfs(next); } break; } case 2: { if(map[now.x][now.y][4]==0) { next.x = now.x; next.y = now.y+1; next.fx = 4; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } case 3: { if(map[now.x][now.y][2]==0) { next.x = now.x-1; next.y = now.y; next.fx = 2; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } case 4: { if(map[now.x][now.y][1]==0) { next.x = now.x+1; next.y = now.y; next.fx = 1; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } } return ; } void stright(Node now) { void Dfs(Node now); Node next; if(map[now.x][now.y][now.fx]==0) { switch(now.fx) { case 1: { next.x = now.x+1; next.y = now.y; next.fx = now.fx; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); break; } case 2: { next.x = now.x-1; next.y = now.y; next.fx = now.fx; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); break; } case 3: { next.x = now.x; next.y = now.y-1; next.fx = now.fx; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); break; } case 4: { next.x = now.x; next.y = now.y+1; next.fx = now.fx; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); break; } } } return ; } void left(Node now) { void Dfs(Node now); Node next; switch(now.fx) { case 1: { if(map[now.x][now.y][4]==0) { next.x = now.x; next.y = now.y+1; next.fx = 4; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } case 2: { if(map[now.x][now.y][3]==0) { next.x = now.x; next.y = now.y-1; next.fx = 3; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } case 3: { if(map[now.x][now.y][1]==0) { next.x = now.x+1; next.y = now.y; next.fx = 1; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } case 4: { if(map[now.x][now.y][2]==0) { next.x = now.x; next.y = now.y-1; next.fx = 2; if(dis[next.x][next.y][0]==0) { sum++; } Dfs(next); } break; } } return ; } void Dfs(Node now) { Node next; if(yn) //如果已经出去了,则不用搜索了 { return ; } if(sum == r*c) //如果所有格子已经经过,则直接返回 { return ; } if(now.x == exitx && now.y == exity && now.fx == 1) //如果到出口且出去则标记并返回 { yn = 1; //标记已经出去了 return ; } if(dis[now.x][now.y][now.fx]==1) //如果这个格子的这个方向以前走过,则直接返回(判重) { return ; } if(dis[now.x]) dis[now.x][now.y][0]++; //标记这个格子经过的次数加一 dis[now.x][now.y][now.fx] = 1; //标记这个格子这个方向走过 right(now); stright(now); left(now); } int main() { int t; scanf("%d",&t); while(t--) { init(); yn = 0; sum = 1; Dfs(p); if(sum==r*c) { printf("YES "); } else { printf("NO "); } } return 0; }
别人的代码:(来源: http://blog.csdn.net/wsniyufang/article/details/6665488)
/* 开始用dfs递归,爆栈了 后来模拟又因为 出迷宫的条件一直wa,细节很重要 */ #include <iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<ctime> using namespace std; #define N 50009 int R,C,ER,EC,num; int map1[505][505]; int map2[505][505]; int vis[505][505]; struct Point { int x,y,f; Point(int _x,int _y,int _f){x=_x;y=_y;f=_f;} }; void init() { scanf("%d%d%d%d",&R,&C,&ER,&EC); memset(vis,0,sizeof(vis)); num=0; for(int i=0;i<2*R-1;i++) { if(i&1) { for(int j=0;j<C;j++) scanf("%d",&map1[i/2][j]); } else { for(int j=0;j<C-1;j++) scanf("%d",&map2[i/2][j]); } } } void dfs(Point s,Point ss) { int ff=s.f; for(;;) { if(!vis[s.x][s.y])num++; vis[s.x][s.y]=1; if(s.x==ss.x&&s.y==ss.y)//注意退出的条件,这里比较复杂 { if((s.f==3&&ff==0)||(s.f==1&&ff==2)) break; if(s.f==ff&&ff==0&&(s.y==0||map2[s.x][s.y-1]==1)) break; if(s.f==ff&&ff==2&&(s.y==C-1||map2[s.x][s.y]==1)) break; } if(s.f==0) { if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } } else if(s.f==1) { if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } } else if(s.f==2) { if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } else if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } } else if(s.f==3) { if(s.x+1<R&&map1[s.x][s.y]==0) { s.x++; s.f=0; } else if(s.y+1<C&&map2[s.x][s.y]==0) { s.y++; s.f=3; } else if(s.x>0&&map1[s.x-1][s.y]==0) { s.x--; s.f=2; } else if(s.y>0&&map2[s.x][s.y-1]==0) { s.y--; s.f=1; } } } } void solve() { Point s=Point(0,ER,0); Point ss=Point(R-1,EC,2); dfs(s,ss); dfs(ss,s); if(num==R*C) puts("YES"); else puts("NO"); } int main() { int Case; scanf("%d",&Case); while(Case--) { init(); solve(); } return 0; }