//HDU 1010 Tempter of the Bone (dfs类题目) //http://acm.hdu.edu.cn/showproblem.php?pid=1010 //开始以为很简单,但后来发现要剪枝的地方很多 //剪枝① 就是搜索已经超出范围了 //剪枝② 已经找到合适的方案,停止查找 //剪枝③ 首先,如果某一点在合适的路线上,那么它的t和步数差一定大于它到终点的最短距离 // 其次,如果某一点在合适的路线上,那么它的t和步数差一定奇数,这个可以用笔画一下图,因为它不能斜方向移动 //剪枝④ 这里是判断通路的总长度有没有比t大,没有的话自然不成功了 #include<iostream> #include<cmath> using namespace std; char m[9][9]; bool find; int dir[][2]={{1,0},{-1,0},{0,1},{0,-1}}; int N,M,t,di,dj; void dfs(int si,int sj,int pt) { if(si>N||sj>M||si<=0||sj<=0) return; //剪枝① if(si==di&&sj==dj&&pt==t) {find=true; return;} //剪枝② int temp=t-pt-(abs(si-di)+abs(sj-dj)); //某一点和t的步数差 if(temp<0||temp%2==1) return ; //剪枝③ int i; for(i=0;i<4;i++) { if( m[ si+dir[i][0] ][ sj+dir[i][1] ] != 'X' ) //因为没说每个点只能走一次,所以要先④再⑤ { m[ si+dir[i][0] ][ sj+dir[i][1] ] = 'X'; //④ dfs( si+dir[i][0] , sj+dir[i][1] , pt+1 ); if(find) return; m[ si+dir[i][0] ][ sj+dir[i][1] ] = '.'; //⑤ } } } int main() { while( scanf("%d%d%d",&N,&M,&t)!=EOF && N||M||t ) { int wall=0; int i,j,si,sj; getchar(); for(i=1;i<=N;i++) { for(j=1;j<=M;j++) { scanf("%c",&m[i][j]); if(m[i][j]=='X') { wall++; continue;} if(m[i][j]=='S') {si=i; sj=j; continue;} if(m[i][j]=='D') {di=i; dj=j;} } getchar(); } if(N*M-wall<=t) //剪枝④ { printf("NO/n"); continue; } find=false; m[si][sj]='X'; dfs(si,sj,0); if(!find) { printf("NO/n"); continue; } printf("YES/n"); } return 0; } 2010-08-09 00:29:06