HDOJ 1010 Tempter of the Bone(搜索,奇偶剪枝)

【题意】:输入三个数N、M、T,分别代表行列时间。迷宫中S代表初始位置,D代表门,'.'代表可以走的路。小狗一秒只移动一格。有解输出YES,没有NO。至关重要的条件: on exactly ,表示正好在T秒时间到达,并且这也是奇偶剪枝的关键。不剪枝的话超时TLE。

【奇偶剪枝】:内容来自百度百科

现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,

如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;

如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证)。

结论:

推广之,若 t-[abs(ex-sx)+abs(ey-sy)] 结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。


【AC代码】:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define MAX 7+1

int N = 0, M = 0, T = 0;
int cnt = -1, res = 0;
int sx = 0, sy = 0, ex = 0, ey = 0;
int stepx[] = {-1,0,1,0}, stepy[] = {0,1,0,-1};
int visited[MAX][MAX];
char maze[MAX][MAX];

void dfs(int x, int y);

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	
	int i = 0, j = 0;
	while (cin >> N >> M >> T && N && M && T)
	{
		//initial
		cnt=-1, res = 0;
		memset(visited, 0, sizeof(visited));
		
		//input
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < M; j++)
			{
				cin >> maze[i][j];
				if ('S' == maze[i][j])
				{
					sx = i, sy = j;
				}
				else if ('D' == maze[i][j])
				{
					ex = i, ey = j;
				}
				else if ('X' == maze[i][j])
				{
					visited[i][j] = 1;
				}
			}
		}
		
		//search
		dfs(sx, sy);
		if (res)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
}

void dfs(int x, int y)
{
	int i = 0;
	if (x<0 || x>=N || y<0 || y>=M)
		return;
	visited[x][y] = 1;
	cnt++;
	if ('D'==maze[x][y] && cnt == T)
	{
		res = 1;
		return;
	}
	int temp = T-abs(ex-sx)-abs(ey-sy);
	if (temp<0 || temp&1)
		return;
	for (i = 0; i < 4; i++)
	{
		if (0 == visited[x+stepx[i]][y+stepy[i]] && !res)
		{
			dfs(x+stepx[i], y+stepy[i]);
		}
	}
	cnt--;
	visited[x][y] = 0;
}

其他:1. 位运算判断奇偶的方法。temp&1。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值