ZOJ2110/HUD1010骨头的诱惑(HDUAC2,ZOJWA但是不知道为什么。。。)

ZOJ2110

题目描述:

一只小狗在一个古老的迷宫里找到一根骨头,当它叼起骨头时,迷宫开始颤抖,它感觉到地面开始下沉。它才明白骨头是一个陷阱,它拼命地试着逃出迷宫。

迷宫是一个N*M大小的长方形,迷宫有一个门。刚开始门是关着的,并且这个门会在第T秒钟开启,门只会开启很短的时间(少于1秒),因此小狗必须恰好在第T秒达到门的位置。每秒钟,它可以向上、下、左或右移动一步到相邻的方格中。但一旦它移动到相邻的方格,这个方格开始下沉,而且会在下1秒消失。所以,它不能在一个方格中停留超过一秒,也不能回到经过的方格。

小狗能成功逃离吗?请帮助它。

输入描述:

输入文件中包含多个测试数据。每个测试数据的第1行为3个整数:NMT,(1<NM<7;0<T<50,分别代表迷宫的长和宽,以及迷宫的门会在第T秒时刻开启。

接下来N行信息给出了迷宫的格局,每行有M个字符,这些字符可能为如下值之一。

X:墙壁,小狗不能进入      S:小狗所处的位置

D:迷宫的门                                                                .:空的方格

输入数据以30表示输入数据结束。

输出描述:

对每个测试数据,如果小狗能成功逃离,则输出“YES”,否则输出“NO

样例输入:

3 4 5
S . . .
. X . X
. . . D
4 4 8
. X . X
. . S .
. . . .
D X . X
4 4 5
S . X .
. . X .
. . X D
. . . .
0 0 0

样例输出

YES

YES

NO

 

Tempter of the Bone

 


 

Time Limit: 2 Seconds                                     Memory Limit:65536 KB                            

 


 

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

 

验证路径

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2110 

 

 

//这道题我考虑用DFS的原因是,这个要在指定时间内逃出,BFS都是求的最小路径,不一定正好是这个时间,不太合适
//另一个这道题的规模不是很大,1<N、M<7;0<T<50,因此考虑是可以用DFS

/*第一次提交TLE超时了,看来剪枝还不够啊。。。增加这个剪枝后还是不行if (kongdi<(T-time)) return 0;*/
/*第二次提交TLE超时。。。后来百度加了个奇数偶数的剪枝,if (0 != (abss(d - T + time)) % 2) return 0但是第三次提交就WA*/
/*第三次提交WA if ((d % 2) != (T - time) % 2) return 0;这样还是WA*/
/*第四次提交WA 发现输出YES NO都应该是大写,改完还是WA 在HDU上就过了。。好吧*/


//后来还是百度了有这么个公式if( d % 2 != (Time-t) % 2 )return;d是当前点与目标点的坐标差。Time - t即从当前点到达目标点需要走多少步。
//这两个值的奇偶性是一致的。如果中间没有墙,那么两者应该是d + x == Time - t。d是从当前点到达目标点的最短路,而这个x,设想一下,往外扩展再走,增加的长宽和必定是偶数。而任何数加上偶数奇偶性不变。

/*然后还有几处剪枝:如果这个矩阵的空格的数目小于等于时间t,那么不可能成功。这在主函数里面可以剪枝。在dfs的过程中,如果发现剩余的时间小于当前位置到终点的最小距离,可以直接判断搜索失败;
如果剩余的时间和当前位置到终点的最小时间的差值是奇数的话,可以判断搜索一定失败,可以剪枝,如果是偶数的话,则可能成功。这个是在http://www.cnblogs.com/liuxueyang/archive/2013/04/06/3003192.html
看到的*/


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#define MAXINT 10

int N = 0;
int M = 0;
int T = 0;
char map[MAXINT][MAXINT];
int visit[MAXINT][MAXINT];
int startx = 0;
int starty = 0;
int endx   = 0;
int endy   = 0;

int dir[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} };

int abss(int a)
{
	if (a<0)
	{
		return -a;
	}
	else
	{
		return a;
	}
}
void init()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < M; j++)
		{
			map[i][j]   = '\0';
			visit[i][j] = 0;
		}
	}
	startx = 0;
	starty = 0;
	endx = 0;
	endy = 0;
	return;
}

int dfs(int x, int y,int time,int kongdi)
{
	int i = 0;
	if ((x<0)||(x>=N)||(y<0)||(y>=M)) return 0;
	if (time > T) return 0;
	if((x == endx) && (y == endy) && (time != T))
	{
		return 0;
	}

	//确定距离
	//如果剩余的时间和当前位置到终点的最小时间的差值是奇数的话,可以判断搜索一定失败
	int d = abss(x-endx) + abss(y-endy);
	//if (0 != (abss(d - T + time)) % 2) return 0;

	if ((d % 2) != ((T - time) % 2)) return 0;

	//如果剩下的可以走的空地少于时间那肯定不对了
	if (kongdi<(T-time)) return 0;

	if ((x == endx)&&(y == endy) &&(time == T))
	{
		return 1;
	}

	for (i = 0; i < 4;i++)
	{
		int x1 = x + dir[i][0];
		int y1 = y + dir[i][1];
		if ((x<0) || (x >= N) || (y<0) || (y >= M)) continue;
		if ('X' == map[x1][y1])continue;
		if (1 == visit[x1][y1])continue;
		visit[x1][y1] = 1;
		if (1 == dfs(x1, y1, time + 1, kongdi - 1))
		{
			return 1;
		}
		else
		{
			//回溯
			visit[x1][y1] = 0;
		}
	}

	return 0;
}

int main()
{
	int i = 0;
	int j = 0;
	int num = 0;
	freopen("input.txt","r",stdin);
	while ((3 == scanf("%d %d %d", &N, &M, &T)) && (0 != N) && (0 != M) && (0 != T))
	{
		init();
		num = 0;
		for (i = 0; i < N;i++)
		{
			scanf("%s",&map[i]);
		}
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < M; j++)
			{
				if ('S' == map[i][j])
				{
					startx = i;
					starty = j;
				}

				if ('D' == map[i][j])
				{
					endx = i;
					endy = j;
				}

				if (('X' != map[i][j]) || ('S' != map[i][j]))
				{
					num += 1;//能走的快数
				}
			}
		}
		//当前点到达目标点的最短路
		int d = abss(startx - endx) + abss(starty - endy);

		//这个剪枝之前也没有,第四次才加的,如果最短路比时间还大,那肯定不行
		if(d > T)
		{
			printf("NO\n");
			continue;
		}

		//如果格子比时间还少,那肯定不行,第四次加的
		if (num <T)
		{
			printf("NO\n");
			continue;
		}

		visit[startx][starty] = 1;
		if (1 == dfs(startx, starty,0,num))
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}

	}
	return 0;
}


 //第二次提交,主要是奇偶性的剪枝没写对,其他还好

//第一次提交超时,剪枝不够啊。。。
//AC,主要还是那个奇偶性的剪枝忘了,这个要牢记
#include <stdio.h>
//这个迷宫也不大,所以可以用DFS
#define MAXINT 10

int abss(int a)
{
	if (a > 0)
	{
		return a;
	}
	else
	{
		return -a;
	}
}

int N = 0;
int M = 0;
int T = 0;
char map[MAXINT][MAXINT];
int visit[MAXINT][MAXINT];
int startx = 0;
int starty = 0;
int endx   = 0;
int endy   = 0;

int dir[4][2] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, {0,-1} };

void init()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXINT; i++)
	{
		for (j = 0; j < MAXINT; j++)
		{
			map[i][j]   = '\0';
			visit[i][j] =  0;
		}
	}
	startx = 0;
	starty = 0;
	endx = 0;
	endy = 0;
	return;
}

int dfs(int x, int y,int time)
{
	int i = 0;
	int x1 = 0;
	int y1 = 0;
	int d = 0;
	if ((x<0)||(x>=N)||(y<0)||(y>=M)) return 0;
	if ((time == T)&&(x == endx)&&(y == endy))
	{
		return 1;
	}

	//剪枝
	//剪枝1已经超时就不要再找了,重新回去
	if (time >= T)
	{
		return 0;
	}

	//剪枝2求当前路径和终点的最短路径是否大于T-time,如果是的话,也不要找了
	//说的其构型
	d = abss(x - endx) + abss(y - endy);
	if ((d%2) != ((T - time)%2))
	{
		return 0;
	}


	for (i = 0; i < 4;i++)
	{
		x1 = x + dir[i][0];
		y1 = y + dir[i][1];
		if ((x1<0) || (x1 >= N) || (y1<0) || (y1 >= M)) continue;
		if ('X' == map[x1][y1]) continue;
		if (visit[x1][y1]) continue;
		visit[x1][y1] = 1;
		if (1 == dfs(x1, y1, time + 1))
		{
			return 1;
		}
		else
		{
			//回溯
			visit[x1][y1] = 0;
		}
	}
	return 0;
}


int main()
{
	int i = 0;
	int j = 0;
	freopen("input.txt","r",stdin);
	while ((3 == scanf("%d %d %d", &N, &M, &T)) && (0 != N) && (0 != M) && (0 != T))
	{
		init();

		for (i = 0; i < N; i++)
		{
			scanf("%s", &map[i]);
		}

		for (i = 0; i < N;i++)
		{
			for (j = 0; j < M; j++)
			{
				if ('S' == map[i][j])
				{
					startx = i;
					starty = j;
				}
				if ('D' == map[i][j])
				{
					endx = i;
					endy = j;
				}
			}
		}

		visit[startx][starty] = 1;
		if (1 == dfs(startx,starty,0))
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值