Curling 2.0 POJ - 3009

本文探讨了一种迷宫游戏中求解从起点到终点最短步数的问题,通过深度优先搜索(DFS)策略,模拟球体在由“0”、“1”组成的网格中移动,击碎障碍并寻找路径的过程,最终输出最短步数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 题意:

      题目很复杂,直接抽象化解释了。给你一个w * h的矩形格子,其中有包含一个数字“2”和一个数字“3”,剩下的格子由“0”和“1”组成,目的是计算从“2”走到“3”的最短步数,“1”代表障碍物,“0”代表可以通行。“2”可以往周围四个方向走,如果往某一个方向走,那么停下来的条件是,当这个方向上存在障碍物“1”,且会停在这个障碍物的前一个格子,并会击碎这个障碍物;如果选择的方向上没有障碍物“1”也没有终点“3”,那么就会一直运动下去,直到出界。如果遇到“3”,那么就算一种到达终点的方法。每选择往一个方向运动,就算一步。如果不能到达或者到达的步数大于10,那么就算失败,输出-1.

    拿题目给的图再说明下吧~

    图a:球可以往上和右运动,往上运动直到遇到障碍物才会停下,如果没有障碍物就会出界;往右运动,走一个格子后就会遇到障碍物,此时球停在第二行第三列,且第二行第四列的障碍物被击碎,变为空白格,即“0”。不能往下运动,因为与球相邻的就存在障碍物“1”,球至少运动一个格子才会击碎阻碍它的障碍物。

    图b:球如果往右运动的话,会停在第二行第二列的位置,且第二行第三列的障碍物会被击碎变为空白格。

    图c:球可以往上,左,右运动,往上和左会出界,往右会停在第二行第三列的位置,且第二行第四列的障碍物会被击碎。

    思路:

      求最短步数首先想到的是BFS,无奈BFS无法回溯,即无法恢复之前的状态,所以实现起来过于复杂。然后只好利用DFS了,但是DFS要搜索整个解答树才能找到最优解,好在题目给的限制条件是深度不能大于10,也就是O(410),1e6的时间复杂度,可以满足题意了。剩下的就是模拟了,注意判断题条件就好,具体看代码吧~

  • #include <iostream>
    #include<stdio.h>
    #include<queue>
    #include<string.h>
    using namespace std;
    const int maxn=101;
    int mp[maxn][maxn];
    int dir[4][2]= {1,0,0,1,-1,0,0,-1};
    int n,m;
    int step;
    int minstep;
    void dfs(int step,int x,int y)
    {
        if(step>10)return;
        for(int i=0; i<4; i++)
        {
            int tx=x+dir[i][0];
            int ty=y+dir[i][1];
            if(mp[tx][ty]!=1)
            {
                while(tx>=0&&tx<n&&ty>=0&&ty<m)
                {
                    if(mp[tx][ty]==3)
                    {
                        if(step<minstep)
                            minstep=step;
                        return;
                    }
                    else if(mp[tx][ty]==1)
                    {
                        mp[tx][ty]=0;
                        dfs(step+1,tx-dir[i][0],ty-dir[i][1]);
                        mp[tx][ty]=1;
                        break;
                    }
                    tx=tx+dir[i][0];
                    ty=ty+dir[i][1];
                }
            }
    
        }
    }
    int main()
    {
        while(scanf("%d%d",&m,&n),n+m)
        {
            int x,y;
            step=0;
            minstep=101;
            for(int i=0; i<n; i++)
                for(int j=0; j<m; j++)
                {
                    scanf("%d",&mp[i][j]);
                    if(mp[i][j]==2)
                    {
                        x=i;
                        y=j;
                    }
                }
            dfs(1,x,y);
            if(minstep>10)
                printf("-1\n");
            else printf("%d\n",minstep);
        }
        return 0;
    }
    

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值