您的位置:首页 > 其它

HDU1010_Tempter of the Bone(DFS+奇偶剪枝+回溯)

2014-04-06 10:15 549 查看
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 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

 

Sample Output

 NO
YES

 

解题报告
做搜索专题的时候做到这题,求是否能在规定时间刚好走出迷宫,原本以为是广度搜索,理解错题意了,只要能在那个时间点走出迷宫,且没有走重复格子就可以,自然用深度搜索,判断条件自然是刚好的时间点走到刚好的地点。。。
超时。。。
网上的解题报告都说用奇偶剪枝。。。
顺便学习下奇偶剪纸。。。

下面是网上摘抄。。。

关于奇偶剪枝

首先举个例子,有如下4*4的迷宫,'.'为可走路段,'X'为障碍不可通过

S...

....

....

...D


从S到D的最短距离为两点横坐标差的绝对值+两点纵坐标差的绝对值 = abs(Sx - Dx) + abs(Sy - Dy) = 6,这个应该是显而易见的。

遇到有障碍的时候呢

S.XX

X.XX

...X

...D


你会发现不管你怎么绕路,最后从S到达D的距离都是最短距离+一个偶数,这个是可以证明的

而我们知道:

奇数 + 偶数 = 奇数

偶数 + 偶数 = 偶数

因此不管有多少障碍,不管绕多少路,只要能到达目的地,走过的距离必然是跟最短距离的奇偶性是一致的。

所以如果我们知道从S到D的最短距离为奇数,那么当且仅当给定的步数T为奇数时,才有可能走到。如果给定的T的奇偶性与最短距离的奇偶性不一致,那么我们就可以直接判定这条路线永远不可达了。

知道了奇偶剪枝,麻麻再也不用担心我的TLE了

在搜索中剪枝效果好像不比直接判断能否到达快。。。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
int n,m,t,f,si,sj,di,dj;
char mmap[10][10];
int vis[10][10];
int dx[]= {0,-1,0,1};
int dy[]= {1,0,-1,0};
void dfs(int x,int y,int step)
{
int i;
if(f)return ;
if(mmap[x][y]=='D'&&step==t)
{
f=1;
return ;
}
//    if(abs(di-x)+abs(dj-y)>t-step)
//        return;
//    if((abs(di-x)+abs(dj-y))%2!=(t-step)%2)
//        return ;
for(i=0; i<4; i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&mmap[xx][yy]!='X')
{
vis[x][y]=1;
dfs(xx,yy,step+1);
vis[x][y]=0;//回溯
}
}
}
int main()
{
int i,j,s,e;
while(~scanf("%d%d%d",&n,&m,&t))
{
memset(mmap,0,sizeof(mmap));
memset(vis,0,sizeof(vis));
if(n==0&&m==0&&t==0)
break;
for(i=0; i<n; i++)
scanf("%s",mmap[i]);
int ans=0;
f=0;
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
if(mmap[i][j]=='S')
{
si=i;
sj=j;
}
else if(mmap[i][j]=='D')
{
di=i;
dj=j;
}
}
if((abs(di-si)+abs(dj-sj))%2!=t%2)
printf("NO\n");
else
{
vis[si][sj]=1;
dfs(si,sj,0);
if(f)printf("YES\n");
else printf("NO\n");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: