您的位置:首页 > 其它

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

2016-12-08 12:10 561 查看
原题链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: