poj3009Curling 2.0

/*这个题走法有两种(抽象为一个格子)一是:一次走一格;二是:一次走到空格的尽头。因此便是一个正常深搜,而不用广搜,因为只需将所有步数中最短的路径长度列出,在搜索每一条路径的时候需要注意这两种走法,下面代码有注释此题博主认为,此题值得学习的是在路径长度的选择和这种奇怪的走法,以及通过最近一段dfs的学习,我的感悟是:无论深搜索怎样变核心思想都是深度的回溯,以及在处理时,对边界一层层的判断,以及题目思路搜索的条理必须清楚,博主的深搜暂时告一段落。*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>//这个头文件是引用了一个最大值INT_MAX

using namespace std;

int w, h;//宽,高
int sx, sy, mmin = INT_MAX;//起点坐标
int mapp[30][30];
int dir[][2] = {{1,0},{-1,0},{0,1},{0,-1}};//四个方向

void dfs(int x, int y, int num)
{
    if(num >= 10) return;
    for(int i = 0; i < 4; i++){
        int dx = x + dir[i][0];
        int dy = y + dir[i][1];
        if(mapp[dx][dy] == 1) continue;
        while(!mapp[dx][dy]){//此时可能是1或3下面需要对这两箱操作和判断此时,同时可能是因为到边界了停下来所以需要判断三点接下来:block,goal,到边界需要回溯到上一个积淀
            dx += dir[i][0];
            dy += dir[i][1];
        }
        if(dx >=0 && dx < h && dy >=0 && dy < w){//这里对边界做了判断,当然block和goal都包含在边界中
            //若是到了block
            if(mapp[dx][dy] == 1){//这里对情况位block作出判断
                mapp[dx][dy] = 0;//按照题目要求将block击碎
                dfs(dx-dir[i][0] , dy-dir[i][1], num+1) ;//回退岛上一个节点继续搜索
                mapp[dx][dy] = 1;//恢复现场
            }
            if(mapp[dx][dy] == 3){//这里对goal作出判断
                if(num+1 < mmin)//因为会有很多种方法走到goal,走到后回溯到上一个点知道把所有路径走完所以只需将这些里最短的路径列出来就好
                mmin = num + 1;
            }
        }
    }
}

int main()
{
    while(scanf("%d%d", &w, &h) != EOF && w+h){
        mmin = INT_MAX;//用来确定最小值而引进的一个变量
        for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            scanf("%d", &mapp[i][j]);
            if(mapp[i][j] == 2){
                mapp[i][j] = 0;
                sx = i;
                sy = j;
            }
        }
    }
        dfs(sx, sy, 0);//起点,步数
        if(mmin < INT_MAX){//若步数超过10不符题意,若等于INT_MAX同样不符题意
            printf("%d\n", mmin);
        }
        else
            printf("-1\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值