杭电ACM1010——深度优先搜索+奇偶剪枝

一个月之前,数据结构看完了深度和广度搜索,做这个搜索题目的时候,总是超时,后来才知道可以进行剪枝可以判断是否可以在T的时间内到达指定的地点。

现在重新做了这道题,看了百度百科的奇偶剪枝,发现一下子就可以理解了,原来这个没有那么的难。这也让我明白了,有时候做题的时候,解决不了,或者看不懂的时候,可以先放一放,等以后再来做,思路拓宽了,没有仅限在这道题中,或许那时候你就可以做出来了,做题的心态和思路很重要。

奇偶剪枝,在百度百科中有详细的讲解和证明,这里不多讲了。

http://baike.baidu.com/link?url=WXb7wOhgR-b_EYehE5y6H0tmdAl_mi8-tBGcMoX6SkAU_l6y5ti9dedLlNoYzreX1tpgCb4mp_xHlEiXY7l6_q

杭电1010这一题的题目大意是:一条狗进入一个神奇的迷宫,一秒走一个空白的地方,狗走过的地方会消失,也就是说狗不能往回走,门在T秒之后打开,且打开很短的时间,狗只有在T秒的时候到达才能离开。

下面是AC的代码:

# include 
# include 
using namespace std;

char str[10][10];
int m, n, t;
int ex, ey;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
bool if_yes;                //布尔变量,来判断是否可以到达
int main()
{
	void dfs(int x, int y, int count);
	while(cin >> m >> n >> t && m != 0 && n != 0 && t != 0)
	{
		int i, j, sx, sy, wall_count = 0;
		getchar();
		if_yes = false;
		memset(str, '\0', sizeof(str));
		for(i = 0; i < m; i++)
		{
			for(j = 0; j < n; j++)
			{
				cin >> str[i][j];
				if(str[i][j] == 'S' || str[i][j] == 's')     //找到起点
				{
					sx = i;
					sy = j;
					str[i][j] = 'X';                        //起点变成墙,避免搜索的时候进来,
				}
				else if(str[i][j] == 'D' || str[i][j] == 'd') //找到终点
				{
					ex = i;
					ey = j;
				}
				else if(str[i][j] == 'X' || str[i][j] == 'x')  //数墙有多少
					wall_count++;
			}
			getchar();
		}
		if(n * m - wall_count >= t)                 //空白的地方必须大于等于时间,这个很明确的,不然到不了,进行剪枝
		{
			dfs(sx, sy, 0);
		}
		if(if_yes)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}
void dfs(int x, int y, int count)
{
	if(ex == x && ey == y && count == t)                //找到了
	{
		if_yes = true;
		return;
	}
	int a = (t - count) - (abs(x - ex) + abs(y - ey));   //算出偏移路径
	if(a % 2 == 1 || a < 0)                               //如果是奇数或者小于0, 进行剪枝
	{
		if_yes = false;
		return;
	}
	for(int i = 0; i < 4; i++)                       //四个方向进行搜索
	{
		if(x + dx[i] < 0 || x + dx[i] > m - 1 || y + dy[i] < 0 || y + dy[i] > n - 1)  //越出边界的情况
			continue;
		if(str[x + dx[i]][y + dy[i]] != 'X' && str[x + dx[i]][y + dy[i]] != 'x')   //如果该位置可以走
		{
			str[x + dx[i]][y + dy[i]] = 'X';         //变成墙,避免重新走过
			dfs(x + dx[i], y + dy[i], count + 1);    //递归进行搜索
			str[x + dx[i]][y + dy[i]] = '.';         //变回来
		}
		if(if_yes)
			break;
	}
}

参考博客:

http://blog.csdn.net/mylovepanning/article/details/8118165

你可能感兴趣的:(杭电)