Tempter 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. 
 

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
 

PS:一开始直接深搜,因为一个全部变量,一直wa,坑了好久,最晚终于被同学发现这个变量。。。。

改了之后提交,超时了。。。

原来有一些点是一开始就不能到终点的,没必要去搜索

如:我们把地图标记为0 1相间

0 1 0 1 0 1 0 1 0 1 0 1 0 1

1 0 1 0 1 0 1 0 1 0 1 0 1 0

0 1 0 1 0 1 0 1 0 1 0 1 0 1

1 0 1 0 1 0 1 0 1 0 1 0 1 0

从图中不难看出,从0走到0、从1走到1都需要偶数步,从0走到1或从1走到0都需要奇数步

正好是0^0 = 0, 1^1 = 0, 1^0 = 0^1 = 1;

所以一开始就可以找出起点跟终点对应的数是0还是1,根据以上运算退出是要走偶数步还是奇数步,然后与输入的步数比较,不一样则可以直接跳过

没必要再搜索了


代码:

#include<iostream>
#include<string>
#include<cmath>
using namespace std;

struct P
{
	int x;
	int y;
}ps,pd;

char map[10][10];
int vis[10][10];
int n, m, t;
int dis[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
bool flag = true;

void dfs(int x, int y, int s)
{
	if (x == pd.x && y == pd.y) //如果走到终点则return
	{
		if (s == t) //如果到终点,时间刚好一样,则标记已经找到了,后面的没必要搜索了
		{
			flag = false;	
		}
		return;
	}
	//如果已经找到或走到该点时,该点到终点的最小时间加上走过的时间超过t,则没必要走下去
	if (!flag || (abs(x - pd.x) + abs(y - pd.y) + s) > t)
	{
		return;
	}
	for (int i = 0; i < 4; ++i)
	{
		int x1 = x + dis[i][0];
		int y1 = y + dis[i][1];
		if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && map[x1][y1] != 'X')
		{
			map[x1][y1] = 'X';
			dfs(x1, y1, s + 1);
			map[x1][y1] = '.';
		}
	}
	return;
}

int main()
{
	//做好0 1 0 1这个表,我暂时只想到这样的方法
	for (int i = 0; i < 10; ++i)
	{
		for (int j = 0; j < 10; ++j)
		{
			if (i % 2 == 0)
			{
				if (j % 2)
				{
					vis[i][j] = 1;
				}
				else
				{
					vis[i][j] = 0;
				}
			}
			else if (j % 2 == 0)
			{
				vis[i][j] = 1;
			}
			else
			{
				vis[i][j] = 0;
			}
		}
	}
	while (cin >> n >> m >> t&&n&&m&&t)
	{
		flag = true;
		int w = 0;
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < m; ++j)
			{
				cin >> map[i][j];
				if (map[i][j] == 'S')
				{
					map[i][j] = 'X';
					ps.x = i;
					ps.y = j;
				}
				else if (map[i][j] == 'D')
				{
					pd.x = i;
					pd.y = j;
				}
				else if (map[i][j] == 'X')
				{
					w++;
				}
			}
		}
		if ((vis[ps.x][ps.y] ^ vis[pd.x][pd.y])) //如果结果为1,则说明需要奇数步
		{
			if (t % 2 == 0) //如果给出的时间为偶数,则不能到达
			{
				cout << "NO\n";
				continue;
			}
		}
		else
		{
			if (t % 2)
			{
				cout << "NO\n";
				continue;
			}
		}
		//如果起点到终点的最短时间大于给出的时间,货值给出的时间加上墙的个数超过地图上格子数量,
		//都说明不能再t时刻到达
		if ((n * m - w <= t) || (abs(ps.x - pd.x) + abs(ps.y - pd.y)) > t)
		{
			cout << "NO\n";
			continue;
		}
		dfs(ps.x, ps.y, 0);
		cout << (flag ? "NO" : "YES") << endl;
	}

	return 0;
}

PS:同学提醒,直接算出最短距离是奇数还是偶数就可以了,不用再打那个0 1 0 1的表了

代码:

#include<iostream>
#include<string>
#include<cmath>
using namespace std;

struct P
{
	int x;
	int y;
}ps,pd;

char map[10][10];
int n, m, t;
int dis[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
bool flag = true;

void dfs(int x, int y, int s)
{
	if (x == pd.x && y == pd.y) //如果走到终点则return
	{
		if (s == t) //如果到终点,时间刚好一样,则标记已经找到了,后面的没必要搜索了
		{
			flag = false;	
		}
		return;
	}
	//如果已经找到或走到该点时,该点到终点的最小时间加上走过的时间超过t,则没必要走下去
	if (!flag || (abs(x - pd.x) + abs(y - pd.y) + s) > t)
	{
		return;
	}
	for (int i = 0; i < 4; ++i)
	{
		int x1 = x + dis[i][0];
		int y1 = y + dis[i][1];
		if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && map[x1][y1] != 'X')
		{
			map[x1][y1] = 'X';
			dfs(x1, y1, s + 1);
			map[x1][y1] = '.';
		}
	}
	return;
}

int main()
{
	while (cin >> n >> m >> t&&n&&m&&t)
	{
		flag = true;
		int w = 0;
		for (int i = 0; i < n; ++i)
		{
			for (int j = 0; j < m; ++j)
			{
				cin >> map[i][j];
				if (map[i][j] == 'S')
				{
					map[i][j] = 'X';
					ps.x = i;
					ps.y = j;
				}
				else if (map[i][j] == 'D')
				{
					pd.x = i;
					pd.y = j;
				}
				else if (map[i][j] == 'X')
				{
					w++;
				}
			}
		}
		if ((abs(ps.x - pd.x) + abs(ps.y - pd.y)) % 2 == 0) //如果最短距离为偶数
		{
			if (t % 2) //如果给出的时间为奇数数,则不能到达
			{
				cout << "NO\n";
				continue;
			}
		}
		else
		{
			if (t % 2 == 0)
			{
				cout << "NO\n";
				continue;
			}
		}
		//如果起点到终点的最短时间大于给出的时间,货值给出的时间加上墙的个数超过地图上格子数量,
		//都说明不能再t时刻到达
		if ((n * m - w <= t) || (abs(ps.x - pd.x) + abs(ps.y - pd.y)) > t)
		{
			cout << "NO\n";
			continue;
		}
		dfs(ps.x, ps.y, 0);
		cout << (flag ? "NO" : "YES") << endl;
	}

	return 0;
}




你可能感兴趣的:(Tempter of the Bone)