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

来源:互联网 发布:多空博弈指标源码 编辑:程序博客网 时间:2024/06/11 14:29
题意:给一幅图,有起点有墙有终点,问能不能在刚好t秒的时间走到终点
DFS + 多重剪枝(奇偶性剪枝)
一开始果断DFS,交上去TLE了。。。用了好几重的剪枝才过。。。。

所以不要小看剪枝,往往优化个成百上千倍。

一.奇偶剪枝
例如 4*4的矩阵
1 0 1 0
0 1 0 1
1 0 10
0 1 0 1
由1到1 由0到0必走偶数步
由1到0 由0到1必走偶数步
所以 根据这个和时间来判断是否成立
例如 
4 4 5
S . X .  
. . X .
. . X .
D . . . 
代码:
    int dis=abs(bx-ex)+abs(by-ey); 
    if((dis+t)%2!=0){printf("NO\n");continue;}  //奇偶剪枝  
S处于1的位置 D处于0的位置 则必须经历奇数的步骤才可以到达

 如果给的时间是3,5,7,都可以 到达,如果给的时间是4,6一定不行

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;char s[10][10];int vis[10][10],d[4][2]={0,1,0,-1,1,0,-1,0};int n,m,ok,t,ex,ey;void DFS(int a,int b,int con){    if(s[a][b]=='D'&&con==t){////在给定的时间时找到出口,查找成功后返回        ok=1;        return ;    }    if(con>=t||ok) return ;//超出时间未找到 放弃    int dis=abs(a-ex)+abs(b-ey);//查找的位置 与终点的距离    if((dis+t-con)%2||(dis>t-con)) return ;// 运动中奇偶 剪枝    vis[a][b]=1;                     //或者剩余的时间到不了既定位置    int x,y,i;    for(i=0;i<4;i++){        x=a+d[i][0];        y=b+d[i][1];        if(x>=0&&y>=0&&x<n&&y<m&&s[x][y]!='X'&&!vis[x][y]){            //前四个 位置剪枝 第五个 不走障碍路 第六个 不走返回路            DFS(x,y,con+1);        }    }    vis[a][b]=0;////将经过 回溯为 未经过}int main(){    int i,j,a,b,ans;    while(scanf("%d%d%d",&n,&m,&t)&&(n!=0&&m!=0&&t!=0)){        memset(vis,0,sizeof(vis));        for(ans=1,i=0;i<n;i++){            scanf("%s",s[i]);            for(j=0;j<m;j++){                if(s[i][j]=='S') {//找到入口位置                    a=i,b=j;                    s[i][j]='X';                }                if(s[i][j]=='.'){//记录可行路的步数,出口也算,所以从1开始加                    ans++;                }                if(s[i][j]=='D'){//z找到出口位置                    ex=i,ey=j;                }            }        }        int dis=abs(a-ex)+abs(b-ey);        if(ans<t||(dis+t)%2) {//可行路的个数小于时间 不行,奇偶剪枝            printf("NO\n");            continue;        }        ok=0;        DFS(a,b,0);        //printf("%d\n",ans);        if(ok==1) printf("YES\n");//正确结果        else printf("NO\n");    }    return 0;}


0 0