7.24提高组模拟第2题 box
这道可恶的题,我写出了伪正解bfs(然而爆零了),听了某大佬的讲解,决定写下这篇博客!!!
【题目描述】
有个桌子长 R 宽 C ,被分为 R * C 个小方格。其中,一些方格上有箱子,一些方格上有按钮,一些方格上有障碍物,一些方格上是空地。现在有个任务,需要把所有箱子推到这些按钮上面。箱子有个特征,只能推不能搬不能拉。现在需要用最少的步数把所有箱子推到按钮上。
当然,箱子和人都只能以格子为单位移动,不存在一部分在格内一部分在格外的情况;只能向四个方向推,箱子和推箱子的队员都不能穿越障碍物。推动的定义是,人的前进方向被箱子挡住,且箱子在顺着前进方向的下一格不是箱子或者障碍物,那么就可以推着箱子和箱子一起前进一步。
【输入格式】
输入第一行有两个整数 R,C(4 <= R, C <= 7),代表桌子的长和宽,接下来一共有 R 行,每行有 C 个字符。
字符的含义:
0:代表空地
1:代表障碍物
2:代表箱子
3:代表按钮
4:人所在的初始地方
输入数据保证障碍物环绕整个地图,箱子数目跟按钮数目相同,箱子最少有一个,不会超过 3 个,队员肯定只有一个。不用考虑箱子初始就按着按钮的情况。保证有解。
【输出格式】
输出只有一行,为解决机关???的最小步数。
【输入样例】
4 5
11111
14231
10231
11111
【输出样例】
4
【分析】
扫一眼题面,再扫一眼数据规模,发现是一道搜索,这里我要说的是bfs
用一个4维数组f[pos][b1][b2][b3]表示人在pos、3个箱子分别在b1、b2、b3时经过的最小步数
用pos数组转坐标为编号
又用r数组转编号为坐标
bfs:
对队员做bfs,判断这种情况下是否会影响到箱子,如果会,再修改箱子的位置即可
不多说,上代码!
【代码】
#include<bits/stdc++.h>
using namespace std;
int n,m,qx,qy,l,t,a[10][10],b[10],v[10],f[50][50][50][50],c[6000001][4],fl[10][10];
int dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1},pos[10][10],r[100][4];
string s;
int cmp(int a,int b){
return a>b;
}
int main(){
cin>>n>>m;
int cnt=0;
for(int i=1;i<=n;i++){
cin>>s;
for(int j=1;j<=m;j++){
cnt++;
pos[i][j]=cnt;
r[cnt][1]=i;r[cnt][2]=j;
a[i][j]=s[j-1]-'0';
if(a[i][j]==4) qx=i,qy=j,a[i][j]=0;
if(a[i][j]==2) b[++l]=pos[i][j];//箱子的位置
if(a[i][j]==3) v[++t]=pos[i][j];//按钮的位置
}
}
memset(f,-1,sizeof(f));
c[1][0]=pos[qx][qy];
c[1][1]=b[1];
c[1][2]=b[2];
c[1][3]=b[3];//c数组
memset(fl,1,sizeof(fl));//fl表示该情况是否遍历过
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]==1) fl[i][j]=0;
for(int k=1,l=1;l<=k;l++){
int ren=c[l][0],b1=c[l][1],b2=c[l][2],b3=c[l][3];
int xren=r[ren][1],yren=r[ren][2];
int x1=r[b1][1],y1=r[b1][2];
int x2=r[b2][1],y2=r[b2][2];
int x3=r[b3][1],y3=r[b3][2];
int sx=f[ren][b1][b2][b3];
fl[x1][y1]=0;fl[x2][y2]=0;fl[x3][y3]=0;
if(b1==v[1]&&b2==v[2]&&b3==v[3]){
cout<<f[ren][b1][b2][b3];
return 0;
}//结束
for(int i=1;i<=4;i++){
int xx=xren+dx[i],yy=yren+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
if(fl[xx][yy]&&f[pos[xx][yy]][b1][b2][b3]==-1){
f[pos[xx][yy]][b1][b2][b3]=sx+1;
c[++k][0]=pos[xx][yy];
c[k][1]=b1;
c[k][2]=b2;
c[k][3]=b3;
}
}//先对人做bfs
int q[4];
q[1]=b1;q[2]=b2;q[3]=b3;
if(pos[xx][yy]==q[2]) swap(q[1],q[2]);//判断是否影响到箱子
if(pos[xx][yy]==q[3]) swap(q[1],q[3]);
if(pos[xx][yy]==q[1]){
int tqx=xx+dx[i],tqy=yy+dy[i];
if(tqx>=1&&tqx<=n&&tqy>=1&&tqy<=m){
if(fl[tqx][tqy]){
q[1]=pos[tqx][tqy];
sort(q+1,q+4,cmp);
if(f[pos[xx][yy]][q[1]][q[2]][q[3]]==-1){
f[pos[xx][yy]][q[1]][q[2]][q[3]]=sx+1;
c[++k][0]=pos[xx][yy];
c[k][1]=q[1];
c[k][2]=q[2];
c[k][3]=q[3];
}
}
}
}
}
fl[x1][y1]=1;
fl[x2][y2]=1;
fl[x3][y3]=1;
}
return 0;
}