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

题意:给一幅图,有起点有墙有终点,问能不能在刚好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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值