hdu1010——Tempter of the Bone (深搜+剪枝)(奇偶性剪枝)

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

题目大意:一只狗看到骨头就上当了,他必须从S逃到D,每一秒走一步,不能停留,走过的路不能再走。X是不能走的,. 是可以走的。

思路:就是普通的深搜+剪枝。剪枝利用奇偶性剪枝。

做的时候就硬写,结果tle了,去看了别人的博客才知道奇偶性剪枝这种东西。奇偶性剪枝放在文章末尾。

#include<bits/stdc++.h>
using namespace std;
int n,m,t,xs,xe,ys,ye;
char mp[10][10];
bool vis[10][10],f;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
void dfs(int now,int x,int y)
{
	if (x==xe && y==ye) {
		if (t==now) f=1;
		return ;
	}
	if (f) return;							
	if (x<0 || x>=n || y<0 || y>=m) return;
	if (now>=t) return;
	int t1=t-now-abs(xe-x)-abs(ye-y);			//奇偶性剪枝
	if (t1<0 || t1&1) return;			
	for (int i=0;i<4;i++) {
		if (mp[x+dx[i]][y+dy[i]]!='X'&&vis[x+dx[i]][y+dy[i]]==false) {
			vis[x+dx[i]][y+dy[i]]=true;
			dfs(now+1,x+dx[i],y+dy[i]);
			vis[x+dx[i]][y+dy[i]]=false;
		}
	}
}
int main()
{
	while (cin>>n>>m>>t) {
		if (!(n||m||t)) break;
		for (int i=0;i<n;i++)
			scanf("%s",mp[i]);
		f=0;
		memset(vis,0,sizeof(vis));
		for (int i=0;i<n;i++) 
			for (int j=0;j<m;j++) {
				if (mp[i][j]=='S') xs=i,ys=j;
				else if (mp[i][j]=='D') xe=i,ye=j;
			}
		vis[xs][ys]=1;						
		dfs(0,xs,ys);
		if (f) puts("YES");
		else puts("NO");
	}
	return 0;
}
奇偶性剪枝

把map以01编号:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
能发现从0开始走,走奇数步一定走到1,走偶数步一定走到0。从1开始走则相反。
所以一个位置S(x1,y1)和一个位置E(x2,y2),他们之间的奇偶性质可以用距离的和来表示。即d=abs(x1-x2)+abs(y1-y2)。如果d是奇数则S和E一个是0,一个是1;d是偶数则两个皆为0或1。
所以这题里奇偶性剪枝就是剪去那些还需要走偶数步但只剩奇数秒或需要奇数步只剩偶数秒的情况。

题外话,今天是第四天集训,第二次学长给我们上课。学长长得真帅,真有又帅又厉害的人在周边=。=

发布了3 篇原创文章 · 获赞 0 · 访问量 26
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览