1 条题解

  • 0
    @ 2025-4-15 11:32:45

    题意分析

    本题是推箱子游戏的变种。给定一个 (N × N) 的迷宫,其中有墙壁、目标单元格。需要选择玩家和箱子的起始位置,使得将箱子推到目标单元格所需的移动步数最大化。游戏规则是玩家只能在空单元格水平或垂直移动,若移动方向有箱子且箱子的下一个单元格为空,则可推动箱子。

    解题思路

    采用广度优先搜索(BFS)的方法。从目标单元格出发,找出所有可能的玩家和箱子的起始位置组合,计算每种组合下将箱子推到目标单元格所需的步数,取其中的最大值。

    分析

    1.由于需要找出最大步数,使用 BFS 可以确保遍历到所有可能的状态,并且能记录每个状态的步数。

    2.状态表示为 (rx, ry, bx, by, d),其中 (rx, ry) 是玩家的位置,(bx, by)是箱子的位置,d 是当前步数。

    实现步骤

    1.读取输入的迷宫信息,找到目标单元格的位置。

    2.初始化状态数组 vst 用于标记已经访问过的状态。

    3.从目标单元格开始,将所有与目标单元格相邻的空单元格作为箱子的起始位置,玩家可以位于箱子的四个相邻空单元格之一,将这些初始状态加入队列。

    4.进行 BFS 搜索,每次从队列中取出一个状态,尝试向四个方向移动玩家。如果移动方向有箱子且箱子的下一个单元格为空,则推动箱子。

    5.更新状态并将未访问过的新状态加入队列,同时更新最大步数。

    代码实现

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<list>
    #include<iostream>
    #include<map>
    using namespace std;
    #define inf 0x3f3f3f3f
    #define Max 110
    inline int max(int a,int b)
    {
        return a>b?a:b;
    }
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    int vst[27][27][27][27],ans;
    char mp[27][27];
    int sx,sy,n;
    struct node
    {
        int rx,ry,bx,by,d;
    };
    int dx[4][2]={0,1,1,0,-1,0,0,-1};
    void bfs()
    {
        int i,x,y,tx,ty;
        node ct,st;
        queue<node>q;
        st.bx=sx,st.by=sy;
        for(i=0;i<4;i++)
        {
            x=sx+dx[i][0];
            y=sy+dx[i][1];
            if(x>=0&&x<n&&y>=0&&y<n&&mp[x][y]!='#')
            {
                ct=st;ct.rx=x;ct.ry=y;
                ct.d=0;
                vst[ct.rx][ct.ry][ct.bx][ct.by]=1;
                q.push(ct);
            }
        }
        while(!q.empty())
        {
            st=q.front();
            q.pop();
            for(i=0;i<4;i++)
            {
                x=st.rx+dx[i][0];
                y=st.ry+dx[i][1];
                tx=st.rx+dx[3-i][0];
                ty=st.ry+dx[3-i][1];
                if(x>=0&&x<n&&y>=0&&y<n&&mp[x][y]!='#'&&(x!=st.bx||y!=st.by))
                {
                    if(tx==st.bx&&ty==st.by)
                    {
                        if(!vst[x][y][st.rx][st.ry])
                        {
                            vst[x][y][st.rx][st.ry]=1;
                            ct.rx=x;ct.ry=y;
                            ct.bx=st.rx;ct.by=st.ry;
                            ct.d=st.d+1;
                            ans=max(ans,ct.d);
                            q.push(ct);
                        }
                    }
                    if(!vst[x][y][st.bx][st.by])
                    {
                        vst[x][y][st.bx][st.by]=1;
                        ct=st;
                        ct.rx=x;ct.ry=y;
                        ct.d=st.d+1;
                        if(ct.bx!=sx||ct.by!=sy)
                        {
                            ans=max(ans,ct.d);
                            q.push(ct);
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        int i,j;
        scanf("%d",&n);
        ans=0;
        for(i=0;i<n;i++)
            scanf("%s",mp[i]);
        for(i=0;i<n;i++)
            for(j=0;j<n;j++)
            {
                if(mp[i][j]=='*')
                {
                    sx=i;
                    sy=j;
                    bfs();
                    printf("%d\n",ans);
                    return 0;
                }
            }
    }
    

    代码说明:

    1.vst[rx][ry][bx][by] 用于标记状态 (rx, ry, bx, by) 是否已经访问过。

    2.mp数组存储迷宫信息。

    3.bfs函数实现了广度优先搜索的核心逻辑。

    4.在 main 函数中,读取输入,找到目标单元格的位置,初始化状态数组,调用 bfs 函数进行搜索,最后输出最大步数。

    • 1

    信息

    ID
    1385
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    9
    已通过
    1
    上传者