• DFS+多回溯--poj3009


    题意

    这道题题意是很有趣的,我记得在勇者斗恶龙六里面有一点,在一个有冰的洞穴里面,人物的移动方式就是这道题所说的方式,不过这道题有一个特殊之处,就是人物碰到墙的同时会在墙面前停下开,同时,面前的墙会消失掉,这就需要我们在遍历时要做好回溯

    这道题是要求最少步数,所以一开始我是想用bfs,但是题目有个条件,就是步数不能超过10,那么这时其实bfs也很快的,而且地图是20*20的,所以就用更好写的dfs啦,不过我觉得bfs应该也是可以的。

    用dfs时要特别特别特别注意好回溯

    但是注意,visit数组肯定是要不得,上一篇博文里,我因为bfs没加visit数组吃了大亏,而这道题我就直接避开了visit,原因的话,如果你思考过这道题,我相信你会明白的。

    我的dfs里面就是对当前节点分别往上下左右搜索,我以我代码中往上搜索的部分为例讲解一下这道题的回溯

     for(int i1=x;i1>=1;i1--){//向上搜索 
            if(map[i1][y]==3){
            ans=min(ans,++steps); //stpes+1不难理解 
            steps--; //这个解同当前ans比较之后,该回溯了,我们先把steps还原 
            return; //回溯 
            }
            if(map[i1][y]==1 && (i1+1)==x) break;
            if(map[i1][y]==1 && (i1+1)!=x){
                    steps++;
                    if(steps>ans || steps>10){
                        steps--; //此路不通 回溯前steps-- 
                        return; //回溯 
                    }
                    map[i1][y]=0;
                    dfs(i1+1,y); //上边的两种回溯退回到了这里。但是注意,并不一定退回到了“往上搜索”的这一句哦,也可能是退回到了“往左右下搜索”的这一行 
                    map[i1][y]=1;
                    steps--;
                    break; //因为从当前dfs的出发点,往上搜索已经得到解,因此break,去试试往别的方向走 
            }
        }

    完整代码:

    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    const int maxn=20+5;
    
    int l,h,bx,by,ex,ey;
    int map[maxn][maxn];
    int ans,steps;
    
    void dfs(int x,int y){
        for(int i1=x;i1>=1;i1--){//向上搜索 
            if(map[i1][y]==3){
            ans=min(ans,++steps);
            steps--;
            return;
            }
            if(map[i1][y]==1 && (i1+1)==x) break;
            if(map[i1][y]==1 && (i1+1)!=x){
                    steps++;
                    if(steps>ans || steps>10){
                        steps--;
                        return;
                    }
                    map[i1][y]=0;
                    dfs(i1+1,y);
                    map[i1][y]=1;
                    steps--;
                    break;
            }
        }
        for(int i2=x;i2<=h;i2++){//向下搜索 
            if(map[i2][y]==3){
            ans=min(ans,++steps);
            steps--;
            return;
            }
            if(map[i2][y]==1 && (i2-1)==x) break;
            if(map[i2][y]==1 && (i2-1)!=x){
                    steps++;
                    if(steps>ans || steps>10){
                        steps--;
                        return;
                    }
                    map[i2][y]=0;
                    dfs(i2-1,y);
                    map[i2][y]=1;
                    steps--;
                    break;
            }
        }
        for(int i3=y;i3>=1;i3--){//向左搜索 
            if(map[x][i3]==3){
            ans=min(ans,++steps);
            steps--;
            return;
            }
            if(map[x][i3]==1 && (i3+1)==y) break;
            if(map[x][i3]==1 && (i3+1)!=y){
                    steps++;
                    if(steps>ans || steps>10){
                        steps--;
                        return;
                    }
                    map[x][i3]=0;
                    dfs(x,i3+1);
                    map[x][i3]=1;
                    steps--;
                    break;
            }
        }
        for(int i4=y;i4<=l;i4++){//向右搜索 
            if(map[x][i4]==3){
            ans=min(ans,++steps);
            steps--;
            return;
            }
            if(map[x][i4]==1 && (i4-1)==y) break;
            if(map[x][i4]==1 && (i4-1)!=y){
                    steps++;
                    if(steps>ans || steps>10){
                        steps--;
                        return;
                    }
                    map[x][i4]=0;
                    dfs(x,i4-1);
                    map[x][i4]=1;
                    steps--;
                    break;
            }
        }
    }
    
    int main(){
        freopen("in.txt","r",stdin);
        while(cin>>l>>h && l!=0 ){
            ans=10000;
            steps=0;
            for(int i=1;i<=h;i++){
                for(int j=1;j<=l;j++){
                    cin>>map[i][j]; 
                    if(map[i][j]==2){
                        bx=i;
                        by=j;
                    }
                    if(map[i][j]==3){
                        ex=i;
                        ey=j;
                    }
                }
            }
            dfs(bx,by);
            if(ans>10) cout<<-1<<endl;
            else cout<<ans<<endl;
            
        }
        return 0;
    }
    柳暗花明又一村
  • 相关阅读:
    python 包管理工具 pip 的配置
    Python 变量作用域 LEGB (下)—— Enclosing function locals
    Python 变量作用域 LEGB (上)—— Local,Global,Builtin
    2020 Java 面试题 小结 (答案慢慢补上,有错误请指出)
    mysql 根据日期(date)做年,月,日分组统计查询
    jvm指令
    正则表达式 分割地址 获取省市区详细地址
    .Net 异常记录
    WCF设计服务协议(一)
    plsql ORA-01789:查询块具有不正确的结果列数
  • 原文地址:https://www.cnblogs.com/ucandoit/p/8672315.html
Copyright © 2020-2023  润新知