E - The Pharaoh's Curse Gym - 101518E 推箱子的迷宫

该博客讨论了一道名为'E - The Pharaoh's Curse Gym'的推箱子问题,要求在最多使用两个箱子的情况下,将箱子推到按钮处并到达终点,目标是最小化步数。由于地图中特定类型格子数量有限,作者提出利用之前解决类似问题的经验,通过为每个格子分配ID来记录箱子状态,以求解此问题。

题目:https://vjudge.net/contest/189729#problem/E
题意:
最多两个箱子,把箱子推到按钮处,然后走到终点的最小步数

这道题目的关键在于他的‘。’的格子数比较小不到100个,所以可以记录两个箱子的状态,用之前的做个的id 来给每个格子标号

#include<bits/stdc++.h>

using namespace std;
#define N 105
int n,m;
int Start,End;
int dx[]={0,1,-1,0},dy[]={1,0,0,-1};
char s[N][N];
int x[N],y[N];
int B[5],X[5];
int id[N][N];
int q,p,tot;
int vis[105][105][105];
struct node{
    int x1,x2,now;
    node (){}
    node(int now,int x1,int x2):now(now),x1(x1),x2(x2){};
};
queue<node>Q;
void insert(int now,int x1,int x2,int w){
    if(vis[now][x1][x2]!=-1)return ;
    vis[now][x1][x2]=w;
    Q.push(node(now,x1,x2));
}
void solve(){
    scanf("%d%d",&n,&m);
    memset(id,0,sizeof(id));
    tot=p=q=0;
    for(int i=1;i<=n;++i){
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;++j){
            if(s[i][j]!='#')id[i][j]=++tot,x[tot]=i,y[tot]=j;
            if(s[i][j]=='S')Start=tot;
            if(s[i][j]=='E')End=tot;
            if(s[i][j]=='B')B[++p]=tot;
            if(s[i][j]=='X')X[++q]=tot;
        }
    }
    if(p>q){
        printf("impossible\n");return ;
    }
    while(q<2)X[++q]=0;
    memset(vis,-1,sizeof(vis));
    while(!Q.empty())Q.pop();
    insert(Start,X[1],X[2],0);
    while(!Q.empty()){
        node tmp=Q.front();Q.pop();
        int now=tmp.now,x1=tmp.x1,x2=tmp.x2,w=vis[now][x1][x2];
        if(now==End){
            int flag=1;
            for(int i=1;i<=p;++i)
                if(x1!=B[i]&&x2!=B[i])flag=0;
            if(flag){
                printf("%d\n",w);       
                return ;
            }
        }
        for(int i=0;i<4;++i){
            int newx1=x1,newx2=x2;
            int nx=x[now]+dx[i],ny=y[now]+dy[i];
            if(!id[nx][ny])continue;
            int newid=id[nx][ny];
            if(newid==x1){
                nx=x[x1]+dx[i],ny=y[x1]+dy[i];
                if(!id[nx][ny]||id[nx][ny]==x2)continue;
                newx1=id[nx][ny];
            }
            if(newid==x2){
                nx=x[x2]+dx[i],ny=y[x2]+dy[i];
                if(!id[nx][ny]||id[nx][ny]==x1)continue;
                newx2=id[nx][ny];
            }
            insert(newid,newx1,newx2,w+1);
        }
    }
    printf("impossible\n");
}



int main(){
    //freopen("in.txt","r",stdin);
    int T;scanf("%d",&T);
    while(T--){
        solve();
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值