1 条题解

  • 0
    @ 2025-8-24 22:58:27

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar carbon_monoxide
    Je suis devenu la personne que j'ai toujours détestée.

    搬运于2025-08-24 22:58:27,当前版本为作者最后更新于2024-07-25 15:07:13,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    还没有看题目的可以戳这里

    这是一道模拟和 bfs 的好题,但是细节很多。

    由于方块有三个状态,因此我们在写常规 bfs 时要多加一个量来表示方块的状态。我用 0 表示直立,1 表示横躺,2 表示竖躺。其中横躺时 x,yx,y 的坐标指向左边的方格,竖躺时 x,yx,y 的坐标指向上边的方格。

    然后就是判断方块的违规操作。一共有两种情况,第一种是直立时站在方格 E 上,第二种是方块在方格 # 上(这里我们在地图的外面加一圈方格 #,就省得判断方块有没有越界了)。此外,方块走回头路也是违规的。

    最后就是方块的移动。

    我个人的代码是这样的:

    //zt表示状态,x与y是坐标,bs表示步数。
    if(!zt){//直立时
        //q.push({x,y,zt,bs});
        q.push({x,y-2,1,bs+1});//向左
        q.push({x,y+1,1,bs+1});//向右
        q.push({x-2,y,2,bs+1});//向前
        q.push({x+1,y,2,bs+1});//向后
    }else if(zt==1){//横躺时
        q.push({x,y-1,0,bs+1});//向左
        q.push({x,y+2,0,bs+1});//向右
        q.push({x-1,y,1,bs+1});//向前
        q.push({x+1,y,1,bs+1});//向后
    }else{//竖躺时
        q.push({x,y-1,2,bs+1});//向左
        q.push({x,y+1,2,bs+1});//向右
        q.push({x-1,y,0,bs+1});//向前
        q.push({x+2,y,0,bs+1});//向后
    }
    

    知道这些坑点后,我们就可以愉快地写代码啦!

    //P10485
    #include<bits/stdc++.h>
    using namespace std;
    int n,m,vis[510][510][3],ans=-1;
    char a[510][510];
    struct node{
    	//坐标,状态,步数
        int x,y,zt,bs;
        /*
        zt=0 X
    
        zt=1 XX
    
        zt=2 X
             X
        */
    }st,ed;//起点,终点
    void bfs(){
    	queue<node> q;
        q.push(st);
        while(!q.empty()){
            int x=q.front().x,y=q.front().y,zt=q.front().zt,bs=q.front().bs;
            //cout<<x<<" "<<y<<" "<<zt<<"\n";
            q.pop();
            if(x==ed.x&&y==ed.y&&zt==ed.zt){//到终点了
    			ans=bs;
    		    return;
    		}
            if(a[x][y]=='E'&&!zt) continue;//直立在E格上
            if(a[x][y]=='#'||a[x][y+1]=='#'&&zt==1||a[x+1][y]=='#'&&zt==2) continue;//越界
            if(vis[x][y][zt]) continue;//同一状态下走过了
            vis[x][y][zt]=1;//标记走过了
            if(!zt){//直立时
                q.push({x,y-2,1,bs+1});
                q.push({x,y+1,1,bs+1});
                q.push({x-2,y,2,bs+1});
                q.push({x+1,y,2,bs+1});
            }else if(zt==1){//横躺时
                q.push({x,y-1,0,bs+1});
                q.push({x,y+2,0,bs+1});
                q.push({x-1,y,1,bs+1});
                q.push({x+1,y,1,bs+1});
            }else{//竖躺时
            	q.push({x,y-1,2,bs+1});
                q.push({x,y+1,2,bs+1});
                q.push({x-1,y,0,bs+1});
                q.push({x+2,y,0,bs+1});
            }
        }
    }
    int main(){
        while(cin>>n>>m&&n&&m){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    cin>>a[i][j];
    		//手动加边界
            for(int i=1;i<=n;i++) a[i][0]='#',a[i][m+1]='#';
            for(int i=1;i<=m;i++) a[0][i]='#',a[n+1][i]='#';
            //找起点
            int f=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(a[i][j]=='X'){
                        if(a[i][j+1]=='X') st.zt=1;//起点是横躺状态
                        else if(a[i+1][j]=='X') st.zt=2;//起点是竖躺状态
                        else st.zt=0;//起点是直立状态
                        st.x=i,st.y=j;
    					f=1;
    					break;
                    }
                }
                if(f) break;
            }
            //找终点
            f=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    if(a[i][j]=='O'){
                        if(a[i][j+1]=='O') ed.zt=1;//终点是横躺状态
                        else if(a[i+1][j]=='O') ed.zt=2;//终点是竖躺状态
                        else ed.zt=0;//终点是直立状态
                        ed.x=i,ed.y=j;
                        f=1;
    					break;
                    }
                }
                if(f) break;
            }
            bfs();//广搜
            if(ans==-1) cout<<"Impossible\n";//无解
            else cout<<ans<<"\n";//有解
            /*
            多测不清空
            爆零两行泪
            */
            memset(vis,0,sizeof(vis));
            ans=-1;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    10237
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者