HDU 1010 Tempter of the Bone - (DFS) 奇偶剪枝

/*
hdu1010 Tempter of the Bone (DFS)
奇偶剪枝: 绕弯的步数-最少的步数(直达) 应该为偶数即可恰好在指定步数到达目的地
http://www.cnblogs.com/zhourongqing/archive/2012/04/28/2475684.html --别人的blog
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
#define CLR(c,v) (memset(c,v,sizeof(c)))

const int M = 10;
const char road = '.';
const char wall = 'X';
const char start = 'S';
const char end = 'D';
const char inqueue = '$';
char *yes = "YES";
char *no = "NO";
int revise[][2] = {{-1,0},
			  {0,-1} , {0,1},
				   {1,0}};

int n,m,t;
char map[M][M];
char *res; // 返回最终结果

struct _P{
	int x,y;
	_P(int x=-1,int y=-1):x(x),y(y){}
	bool operator == (const _P& a) const{
		return ((x==a.x) && (y==a.y));
	}
}S,E; // 起点

template <typename _T>
inline _T _abs(_T a){
	return (a>0)?(a):(-a);
}

void DFS(int step , _P& now){
	if ( now == E){ 
		if (step == t)res = yes; // 恰好t步能到终点
		return;
	}
	if (step >= t || (_abs(t-step - _abs(now.x-E.x) - _abs(now.y-E.y)) & 1) )return;
	step++; 
	for (int i = 0 ; i < 4 ; i++){
		int next_x = now.x + revise[i][0];
		int next_y = now.y + revise[i][1];
		if (next_x >= 0 && next_x < n && next_y >= 0 && next_y < m ){ // 没有出界
			if (map[next_x][next_y] == wall){ // 下一步为墙
				continue;
			}
			char flag  = map[next_x][next_y];
			map[next_x][next_y] = wall;
			DFS(step,_P(next_x,next_y));
			if (res == yes)return;
			map[next_x][next_y] = flag;
		}
	}
}

int main(){
	//freopen("in.txt","r",stdin);
	while(cin >> n >> m >> t && n && m && t){
		for (int i = 0 ; i < n ; i++){
			scanf("%s",map[i]);
			for (int j = 0 ; j < m ; j++){
				if ( start == map[i][j] )
					S = _P(i,j);
				else if(end == map[i][j])
					E = _P(i,j);
			}
		}
		res = no;
		map[S.x][S.y] = wall;
		if (t <= m*n)
			DFS(0,S);
		map[S.x][S.y] = start;
		cout << res << endl;
	}

	return 0;
}


/*
一些容易忽略的极限数据,注意剪枝
7 7 48
D......
.......
.......
.......
.......
.......
......S
7 7 48
......D
.......
.......
.......
.......
.......
S......
7 7 48
S......
.......
.......
.......
.......
.......
......D
7 7 48
......S
.......
.......
.......
.......
.......
D......
4 7 27
S......
.......
.......
......D
3 4 5
S.X.
..X.
...D
4 4 5
S.X.
..X.
..XD
....
0 0 0

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值