Tempter of the Bone —— DFS + 剪枝

题目链接 

参考了两个灰常详细的博客,把奇偶剪枝讲得很清楚,致谢致谢!链接如下

博客链接

奇偶剪枝的详细阐述

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <map>
#define N 10
using namespace std;

int n, m, t;
bool vis[N][N];
char g[N][N];
bool escape = false;
int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
int stx, sty, dorx, dory;


void dfs(int x, int y, int d) // 分别代表坐标和已走步数(距离distance)
{
	if(x == dorx && y == dory && d == t) // 如果到达D时,门刚刚打开
	{
		escape = true;
		return;
	}

	int judge = t - d - (abs(dorx - x) + abs(dory - y)); // 判断在这种状态下还有没有可能到达终点
	// judge的值等于剩余步数 - 最短路径(比较粗略,不考虑墙)
	if(judge < 0 || judge & 1) return; // 如果judge剩余步数不足或者与最短路径的奇偶性不同,剪枝

	for(int i = 0; i < n; i ++)
	{
		int xx = x + dx[i], yy = y + dy[i];
		if(xx >= 0 && xx < n && yy >= 0 && yy < m && !vis[xx][yy] && (g[xx][yy] == '.' || g[xx][yy] == 'D'))
		{
			vis[xx][yy] = true;
			dfs(xx, yy, d + 1);
			if(escape) return; // 如果已经找到了解,返回
			vis[xx][yy] = false;
		}
	}

	return;
}

int main()
{
	while(scanf("%d%d%d", &n, &m, &t) && (n || m || t))
	{

		escape = false;
		int walls = 0; // 记录有多少个墙
		memset(vis, 0, sizeof vis);

		cin.get();
		for (int i = 0; i < n; i ++, cin.get())
		{
			for(int j = 0; j < m; j ++)
			{
				char ch;
				scanf("%c", &ch);
				g[i][j] = ch;
				if(ch == 'X')
				{
					walls ++;
				}
				else if(ch == 'D')
				{
					dorx = i, dory = j;
				}
				else if(ch == 'S')
				{
					stx = i, sty = j;
				}
			}
		}


		if(n * m - walls <= t) // 如果总的可走步数都不够的话,直接返回NO
		{
			puts("NO");
			continue;
		}

		vis[stx][sty] = true;

		dfs(stx, sty, 0);

		if(escape)
			puts("YES");
		else puts("NO");
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Victayria

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值