题目: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();
}
}

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

被折叠的 条评论
为什么被折叠?



