poj 3009 dfs暴力解决最短路

题目就不粘了,题意是这样的:一个带网格的方格板,有两种方格,一种是白色的,一种是网状的。白色表示可以通过,用数字0表示,网状的表示障碍物不能通过,用数字1表示。起点和终点分别在两个白色的上面,分别用数字2、3表示。 

目标就是从起点走到终点,且步数小于等于10。

走法和步数计算比较特殊:选定一个方向后,只要是通的就能走下去,三种情况:1、刚好走到终点;2、下一步是障碍物,没法走了,就停下来了,注意,碰到障碍物虽然会停下来了,但是障碍物也跟着没了,这也是不能用bfs的原因,图的结构会发生变化;3、到板子边界了,既没到终点也没障碍物挡着,就出了板子,也就失败了。这样三种情况下,都算作一步,即选定一个方向后到停下来就算做一步。


这样看的话用“滚”代替“走”比较好理解,题目也是用的石头为对象进行的。


有一些易错点:

1、题意没理解清;

2、方格板横竖搞错了,我原来习惯用x、y标记,然后就乱了,就按照题目给的w、h标记了;

3、三种情况的判定容易乱,要注意位置标记;

4、把位置坐标带入数组的时候,要考虑越界的问题,当然这个编译就没过 了。


贴代码:

#include <iostream>
#include <cstdio>
using namespace std;

int map[30][30],w,h,sw,sh,gw,gh,minstep;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};

int notover(int ch,int cw){//没有越界为1
    if(ch < h && ch >=0 && cw >=0 && cw < w)
        return 1;
    return 0;
}

int notacc(int ch,int cw){//不能通行为真
    if(notover(ch,cw))
        if(!map[ch][cw])
            return 0;//可通行为0
        else
            return 1;//没有越界但是有障碍为1
    return 2;//越界为2
}

void dfs(int ch,int cw,int step){
    if(step >= 10)
        return;
    int nh,nw,tmph,tmpw;
    for(int i = 0; i<4; i++){
        tmph = ch + dir[i][0];
        tmpw = cw + dir[i][1];
        
        if(notacc(tmph,tmpw))//下一格就不能通行,没法走步,换个方向
            continue;

        while(!notacc(tmph,tmpw)){
            if(tmph == gh && tmpw == gw)
                break;
            tmph += dir[i][0];
            tmpw += dir[i][1];
        }

        if(tmph == gh && tmpw == gw){
            if(step + 1 < minstep)
                minstep = step + 1;
            continue;
        }


        if(!notover(tmph,tmpw))
            continue;

        nh = tmph - dir[i][0];
        nw = tmpw - dir[i][1];

        if(nh == gh && nw == gw){
            if(step + 1 < minstep)
                minstep = step + 1;
            continue;
        }


        if(notacc(tmph,tmpw) == 1){//撞到障碍物
            map[tmph][tmpw] = 0;
            dfs(nh,nw,step+1);
            map[tmph][tmpw] = 1;
        }

        if(notacc(tmph,tmpw) == 2){//越界了
            dfs(nh,nw,step+1);
        }
    }

    return;
}

int main(){
    while(1){
        scanf("%d %d",&w,&h);
        if(!w)
            return 0;
        
        minstep = 11;
        for(int i = 0; i < h; i++)
            for(int j = 0 ;j < w; j++){
                scanf("%d",&map[i][j]);

                if(map[i][j] == 2){
                    map[i][j] = 0;
                    sh = i;
                    sw = j;
                }
                
                if(map[i][j] == 3){
                    map[i][j] = 0;
                    gh = i;
                    gw = j;
                }
            }

        dfs(sh,sw,0);

        if(minstep > 10)
            cout<<"-1"<<endl;
        else
            cout<<minstep<<endl;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值