[NOIP模拟] [BFS]box

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; 
} 

猜你喜欢

转载自blog.csdn.net/qq_42754826/article/details/81186385