搜索—template of the bone

直达原题

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.

大意:一个迷宫有N*M格,有一些格是木板可以走,有一些是障碍不能走,给一个起点S和一个终点D,一只小狗从S出发,每步可以走一个地板,在每块底边不能停留,而且走过的地板不能再走,给定一个T问小狗能正好走T步到达终点D吗?

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.

大意:有很多测试用例,每个测试中,第一行输入整数N,M,T(1<N,M<7,0<T<50)后面N行中,每行输入M个字符,有些字符可以这样输入:'X':墙;'S':起点;'D':终点;'.':地板,最后一行输入'0 0 0',表示输入结束。

Output

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

每个测试用例中,如果狗能到达,输出“YES”,否则输出“NO”。

分析

本题最重要的就是剪枝操作,我们可以想到如果已经走了k步,k>T就不用再走了,如果走了k步但小于T,这时如果当前所在位置到终点的距离(曼哈顿距离)大于T-k,那么后续的也不用走了,但当前的优化还是不够的,在这里用奇偶剪枝来进一步优化。f = abs(c-x)+abs(d-y),f是曼哈顿距离,(c,d)是终点位置,(x,y)是当前位置。tmp = T-k-f,tmp为最短路径外要走的步数,tmp大于0就要绕路,这里有一个规律:绕路走的一定是偶数步。所以tmp为偶数可能有解,为奇数一定无解。下面介绍一种图形化直观的方法:
用0,1进行交错标记。如果起点与终点都为0或1,那么走偶数步才能到,否则走要走奇数步,这里用曼哈顿距离判断起点与终点是否相同。进一步解释了上面的奇偶剪枝方法:tmp+k为一共走的步数(为偶数步),如果f为奇数,T为偶数,那就不行,其他情况同理。

代码实现

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
char mp[8][8];
bool flag,visit[8][8];
int n , m ,t;
struct node{
	int x;
	int y;
}start,fin;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int x,int y,int time){
	if(flag)return;
	if(mp[x][y]=='D'){
		if(time == t)
			flag = 1;
		return;
	}
	int tmp =t - time - abs(fin.x - x) - abs(fin.y - y);
	if(tmp < 0)return;
	for(int i = 0;i < 4;i ++){
		int xx = dir[i][0] + x;
		int yy = dir[i][1] + y;
		if(xx>=0&&yy>=0&&xx<m&&yy<n&&!visit[xx][yy]&&mp[xx][yy]!='X'){
			visit[xx][yy] = 1;
			dfs(xx,yy,time+1);
			visit[xx][yy] = 0;
		}
	}
}
int main()
{
	while(~scanf("%d %d %d",&n,&m,&t)){
		if(n==0&&m==0&&t==0)break;
		else
			for(int i = 0;i < m;i ++)
				for(int j = 0;j < n;j ++){
					cin>>mp[i][j];
					if(mp[i][j]=='S')start.x = i,start.y = j;
					if(mp[i][j]=='D')fin.x = i,fin.y = j;
	
			}
	int tmp =t - abs(fin.x - start.x) - abs(fin.y - start.y);
	if(tmp&1){puts("NO");continue;}
	memset(visit,0,sizeof(visit));flag = 0;
	visit[start.x][start.y] = 1;
	dfs(start.x,start.y,0);
	if(flag) puts("YES");
	else puts("NO");
	}

	return 0;
}
posted @ 2023-08-22 01:34  LongDz  阅读(24)  评论(0)    收藏  举报