zoukankan      html  css  js  c++  java
  • 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;
    }
    柳暗花明又一村
  • 相关阅读:
    NGUI的HUD Text的扩展插件学习--(HUDText)的使用
    C#设计模式:外观模式(Facade Pattern)
    NGUI的HUD Text的扩展插件学习--(UIFollowTarget)的使用
    NGUI的怎么在一个Gameobject(游戏物体)中调用另一个Gameobject(游戏物体)的脚本(C#)
    C#设计模式:组合模式(Composite Pattern)
    C#Contains方法的错误理解
    C#.NET动态页面静态化生成
    C++ primer plus读书笔记——第1章 预备知识
    如何判断一个数是2的幂
    C++将数值转换为string
  • 原文地址:https://www.cnblogs.com/ucandoit/p/8672315.html
Copyright © 2011-2022 走看看