推箱子 HDU1254

博客探讨了一种解决HDU1254推箱子问题的方法,通过使用五维数组记录人在不同位置能否推动箱子,并利用BFS搜索答案。虽然解法较为全面,但可能不是最简洁的,对代码能力要求较高,适合追求效率的比赛环境中。

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

题目大意是在说给一张图,给定人的起点和终点,以及箱子的起始位置,问最少箱子推多少格可以到达终点。

感觉自己的做法稍微有点麻烦了。

先是使用五维的数组pushdir[a][b][c][d][i]表示人在(a,b)位置,箱子在(c,d)位置是否能往上下左右四个方向推动。例如人在(0,0),箱子在(3,5)可以往上下左右四个方向推那么pushdir[0][0][3][5][0]=pushdir[0][0][3][5][1]=pushdir[0][0][3][5][2]=pushdir[0][0][3][5][3]=1同理用0表示该方向不能推。

那么只需要给定图中的障碍物的位置既可以把所有的上面的状态处理出来,再根据题目给的箱子的位置,人的起点位置,终点位置。既可以搜索出答案。

虽然这种解法并不是最简短的。但是是最全面的的。而且非常考验自己的代码能力(最后一个小时一直在打,连手都抖起来了)

不过比赛的时候还是追求效率吧。

贴上代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define LL long long
struct node
{
    int x,y;
    node() {};
    node(int xx,int yy)
    {
        this->x=xx;
        this->y=yy;
    };
};
struct node1
{
    int x,y,xx,yy;
    int dep;
    node1() {};
    node1(int x,int y,int xx,int yy,int dep)
    {
        this->x=x;
        this->y=y;
        this->xx=xx;
        this->yy=yy;
        this->dep=dep;
    };
};
int n,m,t,stx,sty,boxx,boxy,edx,edy;
int lastans;
int G[10][10],vis[10][10];
int ansvis[10][10][10][10];
int pushdir[10][10][10][10][4];
int dx[]= {1,-1,0,0}; //down up right left
int dy[]= {0,0,1,-1};
int ddx[]= {-1,1,0,0}; //down up right left
int ddy[]= {0,0,-1,1};
queue<node>q;
void bfs(int i,int j)
{
    while(!q.empty())q.pop();
    q.push(node(i,j));
    vis[i][j]=2;
    node temp;
    while(!q.empty())
    {
        temp=q.front();
        //cout<<temp.x<<" "<<temp.y<<endl;
        q.pop();
        for(int k=0; k<4; k++)
        {
            int newx,newy;
            newx=temp.x+dx[k];
            newy=temp.y+dy[k];
            if(newx<n&&newx>=0&&newy<m&&newy>=0&&vis[newx][newy]!=1&&vis[newx][newy]!=2)
            {

                q.push(node(newx,newy));
                vis[newx][newy]=2;
            }
        }
    }
    return ;
}
queue<node1>qq;
void bfsans()
{
    while(!qq.empty())qq.pop();
    qq.push(node1(stx,sty,boxx,boxy,0));
    ansvis[stx][sty][boxx][boxy]=1;
    node1 temp;
    while(!qq.empty())
    {
        temp=qq.front();

        if(temp.xx==edx&&temp.yy==edy)
        {
            lastans=min(lastans,temp.dep);
        }
        qq.pop();
        for(int i=0; i<4; i++)
        {
            int newx,newy;
            newx=temp.xx+ddx[i];
            newy=temp.yy+ddy[i];

            if(newx<n && newx>=0 && newy<m && newy>=0 && ansvis[temp.xx][temp.yy][newx][newy]==0&&pushdir[temp.x][temp.y][temp.xx][temp.yy][i])
            {
                qq.push(node1(temp.xx,temp.yy,newx,newy,temp.dep+1));
                ansvis[temp.xx][temp.yy][newx][newy]=1;
            }
        }
    }
}


int main()
{
    cin>>t;
    while(t--)
    {
        memset(pushdir,0,sizeof(pushdir));
        memset(vis,0,sizeof(vis));
        cin>>n>>m;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                cin>>G[i][j];
                if(G[i][j]==4)
                {
                    stx=i;
                    sty=j;
                    G[i][j]=0;
                }
                if(G[i][j]==3)
                {
                    edx=i;
                    edy=j;
                    G[i][j]=0;
                }
                if(G[i][j]==2)
                {
                    boxx=i;
                    boxy=j;
                    G[i][j]=0;
                }

            }
        }

        for(int i=0; i<n; i++) //people
        {
            for(int j=0; j<m; j++)
            {
                for(int ii=0; ii<n; ii++) //box
                {
                    for(int jj=0; jj<m; jj++)
                    {
                        memcpy(vis,G,sizeof(vis));
                        if(i==ii&&j==jj||vis[ii][jj]==1||vis[i][j]==1)continue;
                        vis[ii][jj]=1;
                        bfs(i,j);
                        for(int k=0; k<4; k++)
                        {
                            int newx,newy,nnewx,nnewy;
                            newx=ii+dx[k];
                            newy=jj+dy[k];
                            nnewx=ii+ddx[k];
                            nnewy=jj+ddy[k];
                            if(newx<n && newx>=0 && newy<m && newy>=0 && vis[newx][newy]==2&&
                                    nnewx<n && nnewx>=0 && nnewy<m && nnewy>=0 && vis[nnewx][nnewy]!=1)
                            {
                                pushdir[i][j][ii][jj][k]=1;
                                //up,down,left,right
                            }
                        }
                    }
                }
            }
        }
        lastans=inf;
        memset(ansvis,0,sizeof(ansvis));
        bfsans();
        if(lastans==inf)cout<<"-1"<<endl;
        else cout<<lastans<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值