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;
}

 

posted @ 2018-03-29 20:46  柳暗花明_liu  阅读(328)  评论(0编辑  收藏  举报