方法一:
#include<stdio.h> #include<string.h> #include<math.h> char map[10][10]; int n,m,t,di,dj,wall,flag; int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; void dfs(int xi,int xj,int count) { int i,tem; if( xi > n || xj > m|| xi <=0 || xj <=0) { return; } if(count==t && xi==di && xj==dj) { flag=1; } if(flag == 1) return; tem = ( t - count) - abs ( xi - di) - abs( xj - dj); if(tem < 0 || tem%2!=0 ) return ; for(i=0;i<4;i++) { if(map[xi+next[i][0]][xj+next[i][1]]!='X') { map[xi+next[i][0]][xj+next[i][1]]='X'; dfs(xi+next[i][0],xj+next[i][1],count+1); map[xi+next[i][0]][xj+next[i][1]]='.'; } } return ; } int main() { int i,j,si,sj; while(scanf("%d%d%d%*c",&n,&m,&t),n!=0&&m!=0&&t!=0) { wall=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { scanf("%c",&map[i][j]); if(map[i][j]=='S') si=i,sj=j; if(map[i][j]=='D') di=i,dj=j; if(map[i][j]=='X') wall++; } getchar(); } if(n*m-wall<=t) { printf("NO\n"); continue; } flag=0; map[si][sj]='X'; dfs(si,sj,0); if(flag==1) printf("YES\n"); else printf("NO\n"); } return 0; } 方法二: #include<stdio.h> #include<math.h> #include<string.h> char map[10][10]; int xi,xj,di,dj,n,m,t; int next[4][2]={{1,0},{-1,0},{0,1},{0,-1}},book[10][10],flag; void dfs(int xi,int xj,int step) { int i,ti,tj; if(xi==di&&xj==dj) { if(t==step) flag=1; return; } if(step>=t) return; if(map[xi][xj]!='X') { for(i=0;i<4;i++) { ti=xi+next[i][0]; tj=xj+next[i][1]; if(map[ti][tj]!='X'&&ti>=0&&ti<n&&tj>=0&&tj<m&&book[ti][tj]!=1) { book[ti][tj]=1; dfs(ti,tj,step+1); book[ti][tj]=0; if(flag) return; } } } } int main() { while(scanf("%d%d%d",&n,&m,&t),n!=0&&m!=0&&t!=0) { int i,step=0,j; for(i=0;i<n;i++) { getchar(); for(j=0;j<m;j++) { scanf("%c",&map[i][j]); if(map[i][j]=='S') { xi=i; xj=j; } if(map[i][j]=='D') { di=i; dj=j; } } } getchar(); memset(book,0,sizeof(book)); if(abs(xi-di)+abs(xj-dj)>t||(xi+xj+di+dj+t)%2==1) { printf("NO\n"); continue; } book[xi][xj]=1; flag=0; dfs(xi,xj,step); if(flag==1) printf("YES\n"); else printf("NO\n"); } return 0; }
以上两种方法都用到了奇偶剪枝!!!!!
那什么是奇偶剪枝呢!
其实它的理解很绕,内容有介绍起来很多很烦,但是大家要仔细看,并且去理解它。
先看这样的一个矩阵:
矩阵形式如下:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1 从为 0 的格子走一步,必然走向为 1 的格子 。 从为 1 的格子走一步,必然走向为 0 的格子 。
由上面的可以得到以下的结论: 1.从 0 走向 1 (或 1 走向 0 )必然是奇数步。
2.从 0 走向 0( 或 1 走向 1 )必然是偶数步。
So
当遇到下面两种情况时,都可以直接判断不可达!
从 0 走向 0 ,要求时间(所剩的时间)是奇数的。从 1 走向 0 ,要求时间(所剩的时间)是偶数的。
本题的两个解法:
解法1:
tem=(t-count)-abs(xi-di)-abs(xj-dj); if(tem < 0 || tem%2!=0 ) return;
这是它的核心代码。 令 最少需要的步数为a=abs(xi-di)+abs(xi-xj) ,剩下的步数为b=t-count 。(这里就这样表示了,都懂啊!@-@) 则 如果a为奇数,则一定是 从 0 走向 1 (或 1 走向 0)。 如果a为偶数,则一定是 从 0 走向 0 (或 1 走向 1)。 如果b为奇数,则一定是 从 0 走向 1 (或 1 走向 0)。 如果b为偶数,则一定是 从 0 走向 0 (或 1 走向 1)。 因为 偶数-奇数 = 奇数,奇数-偶数 = 奇数,奇数-奇数= 偶数,偶数-偶数=偶数。 所以 b-a得到结果直接判断奇偶就行了。 解法2的代码 里面用一个book数组来标记这个地方是否走过。其他的问题和解法1 大同小异。耐下心来好好分析就知道啦!!!!! 解释了这么多不知道你们是否能明白。。。。。。。。。。。。。。 有问题留言吧!!!!