【问题描述】 有个桌子长 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
【样例说明】 在样例中,最快的方法之一是先向东把第一个箱子推到按钮上,然后向西走 回原处,之 后向南一步,再向东推第二个箱子到按钮上。至此任务完成,共使用了 4 步。 【数据范围】 对 30%的输入数据 :箱子只有一个。 对 100%的输入数据 :4<=R,C<=7。
分析:测试t2,心态不好,没敢调
bfs+储存状态
首先我们将每个位置重新编号
用f[person][box1][box2][box3]来存储现在的状态,即人在person处,三个箱子分别在box1,box2,box3处的状态移动的最小步数。
先扩展人的移动(人不碰到箱子时),再扩展人与箱子一起的移动
#include<bits/stdc++.h> using namespace std; #define N 51 int n,m,cnt,t1,t2,sx,sy; int e[N][N],pos[N][N]; int f[N][N][N][N]; int dx[5]={0,0,0,1,-1}; int dy[5]={0,1,-1,0,0}; int box[N],button[N],cx[N],cy[N],ope[N]; bool vis[N][N]; char c[N]; struct email { int person,box1,box2,box3; }st; email makepair(int x,int y,int w,int z) { email a; a.person=x;a.box1=y;a.box2=w;a.box3=z; return a; } queue<email>que; int main() { scanf("%d%d",&n,&m); memset(f,-1,sizeof(f)); memset(vis,true,sizeof(vis)); for(int i=1;i<=n;i++) { scanf("%s",c); for(int j=1;j<=m;j++) { e[i][j]=c[j-1]-'0'; pos[i][j]=++cnt; cx[cnt]=i;cy[cnt]=j; if(e[i][j]==4){sx=i,sy=j;e[i][j]=0;} if(e[i][j]==2)box[++t1]=pos[i][j]; if(e[i][j]==3)button[++t2]=pos[i][j]; if(e[i][j]==1)vis[i][j]=false; } } f[pos[sx][sy]][box[1]][box[2]][box[3]]=0; st.person=pos[sx][sy];st.box1=box[1];st.box2=box[2];st.box3=box[3]; que.push(st); while(!que.empty()) { email u=que.front();que.pop(); int ps=u.person,b1=u.box1,b2=u.box2,b3=u.box3; int x0=cx[ps],y0=cy[ps]; int x1=cx[b1],y1=cy[b1]; int x2=cx[b2],y2=cy[b2]; int x3=cx[b3],y3=cy[b3]; vis[x1][y1]=false;vis[x2][y2]=false;vis[x3][y3]=false; if(b1==button[1]&&b2==button[2]&&b3==button[3]) { printf("%d",f[ps][b1][b2][b3]); return 0; } int num=f[ps][b1][b2][b3]; for(int i=1;i<=4;i++) { int p=x0+dx[i],q=y0+dy[i]; if(p<1||p>n||q<1||q>m)continue; if(vis[p][q]&&f[pos[p][q]][b1][b2][b3]==-1) { f[pos[p][q]][b1][b2][b3]=num+1; que.push(makepair(pos[p][q],b1,b2,b3)); } ope[1]=b1,ope[2]=b2,ope[3]=b3; if(pos[p][q]==ope[2])swap(ope[1],ope[2]); if(pos[p][q]==ope[3])swap(ope[3],ope[1]); if(pos[p][q]==ope[1]) { int pp=p+dx[i],qq=q+dy[i]; if(pp<1||pp>n||qq<1||qq>m||!vis[pp][qq])continue; ope[1]=pos[pp][qq]; for(int j=1;j<=3;j++) for(int k=j+1;k<=3;k++) if(ope[k]&&ope[k]<ope[j]) swap(ope[k],ope[j]); if(f[pos[p][q]][ope[1]][ope[2]][ope[3]]==-1) { f[pos[p][q]][ope[1]][ope[2]][ope[3]]=num+1; que.push(makepair(pos[p][q],ope[1],ope[2],ope[3])); } } } vis[x1][y1]=true;vis[x2][y2]=1;vis[x3][y3]=1; } return 0; }
’