您的位置:首页 > 其它

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

2018-01-16 20:45 489 查看
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.

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 5

S.X.

..X.

..XD

….

3 4 5

S.X.

..X.

…D

0 0 0

Sample Output

NO

YES

题目概述:

一只小狗在一个古老的迷宫里找到一根骨头,当它叼起骨头时,迷宫开始颤抖,它感到底面开始下沉。它才明白骨头是一个陷阱,它拼命地试着逃出迷宫。
迷宫是一个N*M大小的矩阵,迷宫有一个门,刚开始门是关着的,并且这个门会在第T秒开启,门只会开启很短的时间(小于1秒),
因为小狗必须恰好在第T秒达到门的位置。
所以,它不能在一个方格中停留超过一秒,也不能回到经过的方格。
问小狗能否成功逃离?


寒假训练遇到这个搜索题,正好在看的图论书上碰到了这个题的详细解释。

看了一晚上,算是给弄明白了。

第一次做奇偶剪枝的搜索题。

关于奇偶剪枝奇偶剪枝_百度百科

这里不再赘述。

一开始蠢到没读题,套上BFS就WA了,仔细读题之后才发现不是这样~(不能跟着感觉走啊)

这个题肯定不能用BFS来解决了,BFS找的是最短的路径,而这个题目的意思还可以多绕一些路走使得最终用的时间恰好为t.

详解写在注释里吧。

#include
4000
<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<vector>
#include<queue>
#include<algorithm>
#define max(a,b)   (a>b?a:b)
#define min(a,b)   (a<b?a:b)
#define swap(a,b)  (a=a+b,b=a-b,a=a-b)
#define X (sqrt(5)+1)/2.0  //Wythoff
using namespace std;
typedef long long int LL;
const int MAXL(1e4);
const int MAX(0x3f3f3f3f);
const int mod(1e9+7);
int dir[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
int n,m,t;
char c[10][10];
bool escape;//是否成功逃脱的标志,true代表能够成功逃脱
int index1,index2,sub1,sub2;
void DFS(int x,int y,int cnt)
{
if(x>=1&&x<=n&&y>=1&&y<=m)
{
if(x==sub1&&y==sub2&&cnt==t)
{
escape=true;
return ;
}
//成功逃脱(一开始这里犯了个错误,写成了c[x][y]=='D'&&cnt==t,这样不对,因为每次都会把当前字符设置为墙壁,而后还原,所以这里要判断下标)

//abs(x-sub1)+abs(y-sub2)表示现在所在的个子到目标格子的距离(不能走对角线)
//如果temp<0或者temp为奇数,那就不可能到达(剪枝核心)
int temp=t-cnt-(fabs(x-sub1)+fabs(y-sub2));
if(temp<0||temp&1)
return ;
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0],yy=y+dir[i][1];
if(c[xx][yy]!='X')
{
c[xx][yy]='X';//将当前格设置为墙壁'X'
DFS(xx,yy,cnt+1);
if(escape==true) return ;
c[xx][yy]='.';//恢复现场
}
}
}
return ;
}
int main()
{
ios_base::sync_with_stdio(false);
while(cin>>n>>m>>t&&n+m+t)
{
escape=false;
int wall=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
cin>>c[i][j];
if(c[i][j]=='S')
index1=i,index2=j;
if(c[i][j]=='D')
sub1=i,sub2=j;
if(c[i][j]=='X')
wall++;
}
}
if(n*m-wall<=t)
{
cout<<"NO"<<endl;
continue;
}
//这里加了个搜索前的剪枝。亲测不加这个剪枝跑700+ms,加了之后跑100+ms
c[index1][index2]='X';
DFS(index1,index2,0);
if(escape==true)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: