HDU1010 奇偶剪枝 + 预先筛选 + DFS搜索

0

题目:

题意很清晰,注意走过一个地方就不能再走(所以可以根据这一点,预先筛选掉很多随机数据文件,看code最后一个注释的地方),还要注意是恰好那个时间到达,所以要有足够的地方腾挪(结合刚才那一点因此多了一个预先筛选这样一个剪枝的手段。)

1

分析:

主要学习奇偶剪枝和预先筛选的思想。


补充,奇偶剪枝(摘自百度百科):

现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s
       
|
       
|
       
|
       
+
e
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s
 
 
+
 
|
+
     
|
       
+
e
如图,为一般情况下非 最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);

即,不论怎么走,其走的步数和最短的步数的

2

#include <iostream>
#include <string>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <stdio.h>

using namespace std;
char mat[8][8];
int visted[8][8];
struct points{
    int x;
    int y;
    bool operator ==(points& rhs) const{
        return (x==rhs.x&&y==rhs.y);
    }
}star,endd,cur,t1,t2;
int n;int m;int t;
int flag;
int wall;
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
void Dfs(struct points cur,int time){
    if(time==t){
        return ;
    }
    int val=(t-time)-(abs(endd.x-cur.x)+abs(endd.y-cur.y));
    if(val&1||val<0){///奇偶剪枝,val&1即val是奇数(&按位&,相同为1,不同为0)。
            return;
    }
    struct points next;
    for(int i=0;i<4;i++){
        next.x=cur.x+dir[i][0];
        next.y=cur.y+dir[i][1];
        if(next.x<1||next.x>n||next.y<1||next.y>m) continue;
        if(next==endd&&time+1==t){
            flag=1;
            return ;
        }
        if(mat[next.x][next.y]=='.'){
            mat[next.x][next.y]='X';
            Dfs(next,time+1);
            mat[next.x][next.y]='.';
        }
        if(flag==1){
            return ;
        }
    }
    return ;
}
int main(){

    while(~scanf("%d%d%d",&n,&m,&t)&&n!=0){
        flag=0;
        wall=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>mat[i][j];
                visted[i][j]=0;
                if(mat[i][j]=='S') {
                    star.x=i;
                    star.y=j;
                }
                if(mat[i][j]=='X'){
                    wall++;
                }
                if(mat[i][j]=='D'){
                    endd.x=i;
                    endd.y=j;
                }
            }
        }
        if((n*m-wall)<=t){///注意!!,因为数据是在卡定范围下随机的,所以理应想到,如果该题允许无解的情况,就很可能有很多大数的数据文件都是如此,所以想办法进入DFS前就去掉他们。这里去掉的是,没有多余地方可供腾挪的,因为题意明确指出每一个地方只能到一次。(另外,注意我尝试去掉=,会慢几百ms,所以很多数据的个数都应该是卡在了n*m-wall==t这个点了,之前还以为算法有问题查了好久、)
            cout<<"NO"<<endl;
            continue;
        }
        Dfs(star,0);
        if(flag==1){
            cout<<"YES"<<endl;
        }
        else{
            cout<<"NO"<<endl;
        }
    }
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值