迷宫型的问题,题意:输入迷宫的行数和列数,以及终点开门的时间,然后输入这个迷宫,迷宫中走过的路不能重复走。起点是S,终点是D,墙为X,问从S点出发,能否在D门开的时候正好走出去。题目意思很好理解,直接用DFS搜索就好。
不过当然直接DFS的话肯定会超时,所以这个题目的关键在于要如何剪枝了,如果搜索到边界或是步数已经超过时间了就返回搜索,这是这一类题的硬性剪枝了,一般都肯定会注意到。这个题比较特殊的在于要用到奇偶剪枝的方法来处理(好吧,其实我一开始就是超时了,然后听师哥讲了奇偶剪枝才把这题AC了= =),因为这道题要求是在终点开门的那一刻正好走到,所以可以用到奇偶剪枝。
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
假如说上面就是这个迷宫的图吧,在标为0的地方作为起点,如果规定了走奇数步,那么最后走到的位置一定是在标为1的地方而不可能是在标为0的地方。同样的,如果规定了走偶数步,最后走到的位置就一定是在标0的地方,这就是奇偶剪枝。
所以放到这个题上来看,找到S和D的位置先进行奇偶剪枝,如果不符合就可以直接判断为“NO“了。
下面是AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char mg[10][10]; bool vis[10][10]; int n,m,t; int si,sj,ei,ej; int re,step; int dfs(int a,int b,int step) { if(re) return 0; if(step>t||a<=0||a>n||b<=0||b>m) return 0; if(mg[a][b]=='D'&&step==t) { re=1; return 0; } if(!vis[a-1][b]&&mg[a-1][b]!='X') { vis[a-1][b]=1; dfs(a-1,b,step+1); vis[a-1][b]=0; } if(!vis[a+1][b]&&mg[a+1][b]!='X') { vis[a+1][b]=1; dfs(a+1,b,step+1); vis[a+1][b]=0; } if(!vis[a][b-1]&&mg[a][b-1]!='X') { vis[a][b-1]=1; dfs(a,b-1,step+1); vis[a][b-1]=0; } if(!vis[a][b+1]&&mg[a][b+1]!='X') { vis[a][b+1]=1; dfs(a,b+1,step+1); vis[a][b+1]=0; } return 0; } int main() { int i,j; while(scanf("%d%d%d",&n,&m,&t)!=EOF) { if(n==0&&m==0&&t==0) break; memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { cin>>mg[i][j]; if(mg[i][j]=='S') { si=i; sj=j; vis[i][j]=1; } if(mg[i][j]=='D') { ei=i; ej=j; } } } re=0; if(t%2==0) { if(((si+sj)%2==0&&(ei+ej)%2==1)||((si+sj)%2==1&&(ei+ej)%2==0)) { cout<<"NO"<<endl; continue; } } else if(t%2==1) { if(((si+sj)%2==0&&(ei+ej)%2==0)||((si+sj)%2==1&&(ei+ej)%2==1)) { cout<<"NO"<<endl; continue; } } t=dfs(si,sj,0); if(re) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }