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


原题链接:Here! ZOJ 2110也是这道题

题意:有一个N x  M 大小的maze,从起点 ' S ' 出发到达出口 ' D ' ,每走一步需要1s,能否恰好在T秒时到达出口。
分析:一开始普通DFS,T了,所以需要奇偶剪枝,还有一个有意思的剪枝是 ① N*M - wall <= T ,从其他大神处get到的,更有意思的是如果等式 ① 不加 = ,A掉的时间是936s,加上 = ,A掉的时间是 265s。不加等号更好理解,根本没有足够长的路来到达 ' D ' ,直接NO ; 加上后会出现一个问题,有时能够恰好到,有时却不能。(可能是数测试数据的问题)

奇偶剪枝link:Here!

注意:输入时用%s,如果用两个for + getchar() 会Wrong,测试数据中的空格好像有问题,我因为这个原因Wrong了整整一页!!!

例如:

恰好到达

4 4 5
S X X X
.  X X X
.  .  .  D
X X X X


不能到达:

4 4 5
S X X X
.  X X X
.  X .  D
X X .  X


CODE:

/*
	Note:
		普通做法一直T 
		肯定是剪枝喽,奇偶剪枝
*/
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
//#define test

const int maxn = 7+3;
int n,m,t;
char G[maxn][maxn];
int vis[maxn][maxn];
struct Node{
	int x,y;
}s,e;
bool ok;

const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};

bool judge(int x,int y){
	if(x>=0 && x<n && y>=0 && y<m)	return true;
	return false;
}
void dfs(int x,int y,int step){
	
	if(x==e.x && y==e.y && step==t){ ok=true; return; }
	if(ok)	return;
	
	int tt=t-step-(abs(x-e.x)+abs(y-e.y));
	if( tt<0 || tt&1 )	return; 		// 奇偶剪枝 
	
	vis[x][y]=1;
	for(int i=0;i<4;i++){
		int tx=x+dx[i] , ty=y+dy[i];
		if( judge(tx,ty) && !vis[tx][ty] && G[tx][ty]!='X'){
			vis[tx][ty]=1;
			dfs(tx,ty,step+1);
			vis[tx][ty]=0;
		}
	}
}
int main(){
	#ifdef test
		freopen("Hdu 1010 Tempter of the Bone.txt","r",stdin);
	#endif
	while(scanf("%d%d%d",&n,&m,&t)!=EOF && (n+m+t)){
		
		memset(vis,0,sizeof(vis));
		ok=false;
		int wall=0;		// 记录wall的数量 
		for(int i=0;i<n;i++)	scanf("%s",G[i]);			// 不要用写成两个循环然后用getchar()!!! wrong了一页 
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(G[i][j]=='S')	s.x=i , s.y=j;
				if(G[i][j]=='D')	e.x=i , e.y=j;
				if(G[i][j]=='X') 	wall++;
			}
		}
		
		if(n*m-wall <= t){ printf("NO\n"); continue; }		// 同样AC 无= 936s  有= 265s 
		
		vis[s.x][s.y]=1;
		dfs(s.x,s.y,0);
		
		if(ok)	printf("YES\n");
		else	printf("NO\n");
	}
	return 0;
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值