您的位置:首页 > 其它

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

2016-11-16 20:56 555 查看
Tempter of the Bone

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 111149 Accepted Submission(s): 30144

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的地图,由一个S,一个D,X和.组成,S代表开始位置,D代表终点位置,X代表墙,.代表可以走的路。给你时间t,问能否恰好在t时刻从起点走到终点。

思路:

一直深搜直到找到答案,但如果不进行优化的话会超时,所以要进行剪枝。此题的核心剪枝是奇偶剪枝。

剪枝

搜索的过程其实就是一个建立递归树的过程

而剪枝,顾名思义就是剪去这棵树上我们所不需要的分枝

当我们通过搜索建立递归树的时候,若到某个节点之后其所有子节点一定不满足题目条件,则没有继续搜索下去的必要,所以直接返回上一层,节省了时间和空间。而从树的角度来看,则是将其一个子树直接减去,故称剪枝。

剪枝大体可以分为两类:

1:可行性剪枝

奇偶剪枝就是一种可行性剪枝,我们根据所给开始坐标S,终点坐标D以及时间t可以直接判断有没有可能,若无可能,直接不搜索,输出NO

2:最优性剪枝

最优性剪枝一般是求最优解。如搜索最短路,将最小路数保存,若路数大于最小路数,直接返回上一层,未被搜索的那一块就是被剪去了

在我的理解中, 可行性剪枝是针对整棵树,判断这棵树是否有建立的必要,而最优性剪枝则是针对子树的,将一些确定不符的子树剪去,以优化时间和空间。

奇偶剪枝:

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

所以所给时间奇偶性==abs(sx-ex)+abs(sy-ey) //s 开始 e 结束

代码:

/*************************************************************************
> File Name: s5_A.cpp
> Author: SIU
> Created Time: 2016年11月05日 星期六 19时58分23秒
************************************************************************/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int visit[10][10];
char map[10][10];
int n,m,k;
int flag=0;
void dfs(int x,int y,int count)
{
int next[4][2]=
{
{1,0},
{0,1},
{-1,0},
{0,-1}
};
if(map[x][y]=='D'&&count==k)
{
flag=1;
return ;
}
if(flag==1)
return ;
for(int i=0;i<4;i++)
{
int tx=x+next[i][0];
int ty=y+next[i][1];
if(tx<0||tx>=n||ty<0||ty>=m)
continue;
if(map[tx][ty]!='X'&&visit[tx][ty]==0)
{
visit[tx][ty]=1;
dfs(tx,ty,count+1);
visit[tx][ty]=0;
}
}
return ;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
flag=0;
if(n==0&&k==0&&m==0)
break;
memset(visit,0,sizeof(visit));
for(int i=0;i<n;i++)
scanf("%s",&map[i]);
int sx,sy;
int ex,ey;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(map[i][j]=='S')
{
sx=i;
sy=j;
}
if(map[i][j]=='D')
{
ex=i;
ey=j;
}
}
}
int item=abs(sx-ex)+abs(sy-ey);
if(item%2!=k%2)
{
printf("NO\n");
continue;
}
if(n*m<k)
{
printf("NO\n");
continue;
}
visit[sx][sy]=1;
dfs(sx,sy,0);
if(flag==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}


PS:附一篇很好的搜索博客:http://www.cppblog.com/menjitianya/archive/2015/10/09/211980.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: