hdu 1010 dfs+奇偶剪枝

http://acm.hdu.edu.cn/showproblem.php?pid=1010

一开始看7*7以为不需要进行剪枝结果。妥妥的超时了。。跑去学习了下奇偶剪枝法。。主要的思想就是当前点到终点所要走的距离应该是他们之间的最短距离加上一个偶数的距离。。不可能是一个奇数。。奇数+偶数=奇数    偶数+偶数=偶数。 所以就能判断总时间必须和最短距离必须同奇偶。。这还可以推广到迷宫中的每一步,对于每一步来说剩下的时间和剩下的最短距离必须是同奇偶。。奇数-奇数=偶数  偶数-偶数=偶数。

那么这题就可以运用两个剪枝。

1、判断剩下的时间 - 剩下的最短距离是否小于零,如果是,必不能抵达(当然这也包含了剩下时间小于零的情况)

2、判断剩下的时间 - 剩下的最短距离是否为偶数,如果是,就能代表他们两个同奇偶,就有可能到达。

背景:在写这道题的过程中我还发现了,自己会犯的一个小错误。。就是剪枝后如果不满足要回溯,在回溯之前应该要将这个点的标记取消,避免之后这个点无法走。。

代码:

//可以写为注释这种写法,就不需要对起点进行标记,但是在剪枝后回溯之前要记得进行还原标记 
//也可以写成在进入dfs前后进行标记跟还原,但是这样无法对起点进行标记,要记得在主程序中进行对起点的标记 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,t;
int d1[4] = {0,0,1,-1};
int d2[4] = {1,-1,0,0};
bool visit[10][10];
char map[10][10];
int sx,sy,ex,ey;
int ok ;
void dfs(int x,int y,int time)
{
	//visit[x][y] = true;
	if(ok==1) return ;   //注意找到答案后要返回 
	int temp = t-time-(abs(ex-x)+abs(ey-y));
	if(temp<0||temp%2!=0)
	{
		//visit[x][y] =false;
		return ;
	}
	if(x==ex && y==ey && time==t)
	{
		ok = 1;
		cout << "YES\n";
		return;
	}
	for(int i = 0;i < 4;i++)
	{
		int dx = x+d1[i];
		int dy = y+d2[i];
		if(dx>=0&&dx<n&&dy>=0&&dy<m&&map[dx][dy]!='X'&&!visit[dx][dy])
		{
			visit[dx][dy] = true;
			dfs(dx,dy,time+1);
			visit[dx][dy] = false;
		}
	}
	//visit[x][y] = false;
}
int main()
{
	while(cin >> n >> m >> t && (n||m||t))
	{
		ok = 0;
		memset(visit,0,sizeof(visit));
		for(int i = 0;i < n;i++)
		{
			for(int j = 0;j < m;j++)
			{
				cin >> map[i][j];
				if(map[i][j]=='S')
				{
					sx = i;
					sy = j;
				}
				if(map[i][j]=='D')
				{
					ex = i;
					ey = j;
				}
			}
		}
		visit[sx][sy] = true;  //写为注释那种写法就不需要标记起点 
		dfs(sx,sy,0);
		if(!ok) cout << "NO\n";
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值