HDU 1010 Tempter of the Bone(DFS + 剪枝)

来源:互联网 发布:动漫壁纸软件下载 编辑:程序博客网 时间:2024/06/06 07:00


Tempter of the Bone
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u


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. 
 

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. 
 

Output

For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise. 
 

Sample Input

4 4 5S.X...X...XD....3 4 5S.X...X....D0 0 0
 

Sample Output

NOYES
 


题目大意:

一个小狗在城堡里捡起一块骨头,城堡开始晃动,城堡的大门被关闭,已知城堡的大门会在T秒是开启一下(开启的时候不超过一秒就会关闭不再开启),问小狗能不能逃出去。

输入:输入 n , m , t  表示城堡为 n * m 的,大门在 t 秒后开启一次。

   接下来输入城堡的地图,'S' 小狗的位置         'D'   大门的位置

   '.'  道路,能够走      'X'    墙,不能走

分析:

根据题意可知,就是让判断能不能在 t 秒这一时刻到达  D  的位置,如果可以,那么就能够逃出,如果不可以,那就不可以。   不用说,直接上深搜,判断,如果有结果就标记,输出。

如果就这样直接搜索,提交,那么恭喜你,将会得到一个 TLE , 因此就知道需要剪枝了,剪枝主要是对该点能不能到达进行剪,其中主要剪的是一个奇偶步的剪枝。剪枝分析如下

/* *  剪枝 1: 横纵坐标差的和剪枝,时间小于|横坐标差| + |纵坐标差|  那么就不能到达 *  剪枝 2;奇偶步的判断  ,无论如何走,都可以认为是由横坐标差 + 纵坐标差 步数到达后  *          再绕几步路,在绕路过程中所消耗的步数必须是偶数才有可能回到终点 *          所以 time -  |坐标差| - |纵坐标差| 必须是偶数,否则不能到达  */






附上代码

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <queue>#include <algorithm>using namespace std;int n,m;char Map[10][10];int visit[10][10];int t[4][2] = {0,1,1,0,-1,0,0,-1};int flag;void DFS(int cur_x,int cur_y,int time){if(flag || time < 0)   //  剪枝 4: 当所消耗的时间大于所需要的时间时,没有必要再进行搜索,直接返回 return;if(Map[cur_x][cur_y] == 'D' && time == 0)   // 搜索到结果,标记,返回。 {flag = 1;return; }for(int i = 0;i < 4;i++){int tx = cur_x + t[i][0];int ty = cur_y + t[i][1];if(tx >= 0 && tx < n && ty >= 0 && ty < m && !visit[tx][ty] && (Map[tx][ty] == '.' || Map[tx][ty] == 'D')){visit[tx][ty] = 1;DFS(tx,ty,time - 1);visit[tx][ty] = 0;if(flag)                   // 剪枝 3 : 找到以后返回,结束搜索 return;}}}int main(){int time;while(~scanf("%d%d%d",&n,&m,&time) && n + m + time){flag = 0;int begin_x,begin_y,end_x,end_y; memset(Map,0,sizeof(Map));memset(visit,0,sizeof(visit));for(int i = 0;i < n;i++){scanf("%s",Map[i]);for(int j = 0;j < m;j++){if(Map[i][j] == 'S'){begin_x = i;begin_y = j;}if(Map[i][j] == 'D'){end_x = i;end_y = j;}}}/* *  剪枝 1: 横纵坐标差的和剪枝,时间小于|横坐标差| + |纵坐标差|  那么就不能到达 *  剪枝 2;奇偶步的判断  ,无论如何走,都可以认为是由横坐标差 + 纵坐标差 步数到达后  *          再绕几步路,在绕路过程中所消耗的步数必须是偶数才有可能回到终点 *          所以 time -  |坐标差| - |纵坐标差| 必须是偶数,否则不能到达  */if(abs(begin_x - end_x) + abs(begin_y - end_y) > time || (time - abs(begin_x - end_x) - abs(begin_y - end_y)) & 1){printf("NO\n");continue;}DFS(begin_x,begin_y,time);if(flag)printf("YES\n");elseprintf("NO\n");}return 0;}


0 0
原创粉丝点击