Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 149724 Accepted Submission(s): 39929
Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze began to shake, and the doggie could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
The maze was a rectangle with sizes N by M. There was a door in the maze. At the beginning, the door was closed and it would open at the T-th second for a short period of time (less than 1 second). Therefore the doggie had to arrive at the door on exactly the T-th second. In every second, he could move one block to one of the upper, lower, left and right neighboring blocks. Once he entered a block, the ground of this block would start to sink and disappear in the next second. He could not stay at one block for more than one second, nor could he move into a visited block. Can the poor doggie survive? Please help him.
Input
The input consists of multiple test cases. The first line of each test case contains three integers N, M, and T (1 < N, M < 7; 0 < T < 50), which denote the sizes of the maze and the time at which the door will open, respectively. The next N lines give the maze layout, with each line containing M characters. A character is one of the following:
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
Output
For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise.
Sample Input
4 4 5 S.X. ..X. ..XD .... 3 4 5 S.X. ..X. ...D 0 0 0
Sample Output
NO YES
Author
ZHANG, Zheng
Source
原理:遍历+剪枝
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<math.h> char maze[8][8]; int n,m,t,flag,ei,ej,t1; void dfs(int i,int j) { if(maze[i][j]=='D') //首先判断起始坐标是不是终点 { if(t1==t) //若是终点,判断跳跃次数是否与要求相同 { flag=1; return; } else { t1--; //因为之前到终点跳的这一次加上了,但却又不符合条件,故再减掉 return; } } int temp=abs(i-ei)+abs(j-ej); temp=t-temp-t1; if(temp&1) {t1--;return ;}//奇偶剪枝 maze[i][j]='X'; int i1,j1; for(int di=0;di<4;di++) { switch(di) { case 0:i1=i-1;j1=j;break; case 1:i1=i+1;j1=j;break; case 2:i1=i;j1=j+1;break; case 3:i1=i;j1=j-1; } if(i1>=0&&i1<n&&j1>=0&&j1<m&&maze[i1][j1]!='X') { t1++; dfs(i1,j1); } } maze[i][j]='.'; t1--; } int main() { int x,y; while(scanf("%d%d%d",&n,&m,&t),n&&m&&t) { getchar(); //由于回车也是字符,如不消除会存入数组,使用getchar()吸收回车 for(int i=0;i<n;i++) { for(int u=0;u<m;u++) { scanf("%c",&maze[i][u]); //双重循环,对全局二维数组map 进行赋值 if(maze[i][u]=='S') //记录开始坐标 { x=i; y=u; } if(maze[i][u]=='D') //记录终点坐标 { ei=i; ej=u; } } getchar(); //每行输入结束时会再输入一个回车键,再次吸收掉 } t1=flag=0; dfs(x,y); if(flag) printf("YES\n"); else printf("NO\n"); } return 0; } /* #include<stdio.h> #include<math.h> int sum,t,m,n,e,ex,ey; char map[7][8]; struct direction { int x; int y; }d[4]={{0,1},{1,0},{0,-1},{-1,0}}; void fun(int sx,int sy) { if(map[sx][sy]=='D') //首先判断起始坐标是不是终点 { if(sum==t) //若是终点,判断跳跃次数是否与要求相同 { printf("YES\n"); //输出YES,e变化,并结束当前函数的调用 e++; return; } else { sum--; //因为之前到终点跳的这一次加上了,但却又不符合条件,故再减掉 return; } } if((t-sum-(abs(ex-sx)+abs(ey-sy)))%2!=0) //奇偶剪枝:在进行深搜前就可排除一些不可能的坐标,防超时 { sum--; return; } int tx,ty,i; //用tx,ty 表示下一个坐标并带入递归,可保存上一个坐标 map[sx][sy]='X'; //使得深搜时不会再搜之前的点 for(i=0;i<4;i++) //一共有4个方向,每个方向都要进行搜查 { tx=sx+d[i].x; //结构体数组d[4]记录了每个方向的偏移量,可使点发生移动 ty=sy+d[i].y; //例如,现位于(3,4)处,向上移动一个 , x 不变 y+1 则使用d[0] if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='X') //不越界且不是墙 { sum++; //可以过去,跳一次 fun(tx,ty); //进行递归,暴力搜查。将现在的坐标作为起始点带入函数 } //这样后,每个点都会搜查4个方向,若下一个点搜查完毕,就会返回上一个点 } map[sx][sy]='.'; //若4个方向访问结束,便将'X'变回'.'表明退了回去,点重置,上一点换方向改变路线时,此点仍可过 sum--; //退了回去,次数减1 } int main() { int i,u,sx,sy; while(~scanf("%d%d%d",&n,&m,&t)&&(n!=0&&m!=0&&t!=0)) { sum=0;e=0; //将题中时刻相同理解成 sum :表示跳了几次,用sum与t进行比较 getchar(); //由于回车也是字符,如不消除会存入数组,使用getchar()吸收回车 for(i=0;i<n;i++) { for(u=0;u<m;u++) { scanf("%c",&map[i][u]); //双重循环,对全局二维数组map 进行赋值 if(map[i][u]=='S') //记录开始坐标 { sx=i; sy=u; } if(map[i][u]=='D') //记录终点坐标 { ex=i; ey=u; } } getchar(); //每行输入结束时会再输入一个回车键,再次吸收掉 } //到此基本图表输入与记录完成 fun(sx,sy); //将起始坐标带入函数 if(e==0) printf("NO\n"); //此处用e来判断:e为全局变量,若在函数中输出YES,e值会变化,则不会输出NO } return 0; } */