hdu1254 推箱子(两种解法)
传送门:https://vjudge.net/problem/HDU-1254
题意:就是一个箱子的推箱子,问箱子最少走多少步到达目的地。
因为我c++实训打算写个推箱子游戏,看见有这题就过来打一下。。。。
这题两种解法
第一种:就是普通的bfs,只是记录状态有四个值,分别是人的坐标和箱子的坐标,由于n很小,所以vis[n][n][n][n]内存还是可以接受的。
1 // Cease to struggle and you cease to live 2 #include <iostream> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <stack> 12 using namespace std; 13 typedef long long ll; 14 int mp[10][10]; 15 struct node{ 16 int px,py,bx,by,step; 17 }; 18 int dx[]={0,0,1,-1}; 19 int dy[]={1,-1,0,0}; 20 int vis[10][10][10][10]; 21 int main() { 22 int T;scanf("%d",&T); 23 for(int t=1;t<=T;++t){ 24 queue<node> Q; 25 node a; 26 a.step=0; 27 memset(vis,0x3f3f3f3f,sizeof(vis)); 28 int n,m;scanf("%d%d",&n,&m); 29 int psx,psy,bsx,bsy; 30 for(int i=1;i<=n;++i){ 31 for(int j=1;j<=m;++j){ 32 scanf("%d",&mp[i][j]); 33 if(mp[i][j]==4){ 34 a.px=i;a.py=j; 35 } 36 else if(mp[i][j]==2){ 37 a.bx=i;a.by=j; 38 } 39 } 40 } 41 vis[a.bx][a.by][a.px][a.py]=0; 42 Q.push(a); 43 int ans=0x3f3f3f3f; 44 while(!Q.empty()){ 45 node u=Q.front(); 46 Q.pop(); 47 if(mp[u.bx][u.by]==3){ 48 ans=min(ans,u.step); 49 } 50 for(int i=0;i<4;++i){ 51 node v; 52 int xx=u.px+dx[i],yy=u.py+dy[i]; 53 if(xx<1 || xx>n || yy<1 || yy>m) continue; 54 if(mp[xx][yy]==1) continue; 55 int bxx=u.bx,byy=u.by; 56 int ok=0; 57 if(xx==u.bx && yy==u.by){ 58 ok=1; 59 bxx=u.bx+dx[i],byy=u.by+dy[i]; 60 if(bxx<1 || bxx>n || byy<1 || byy>m) continue; 61 if(mp[bxx][byy]==1) continue; 62 } 63 if(vis[bxx][byy][xx][yy]<=u.step+ok) continue; 64 v.px=xx;v.py=yy;v.bx=bxx;v.by=byy;v.step=u.step+ok; 65 Q.push(v); 66 vis[bxx][byy][xx][yy]=u.step+ok; 67 } 68 } 69 if(ans==0x3f3f3f3f) puts("-1"); 70 else printf("%d\n",ans); 71 } 72 return 0; 73 }
第二种:第二种解法是在网上学来的。因为箱子最少步,所以肯定是对箱子bfs,但是箱子移动的前提是人能够到箱子的后面,所以在箱子的bfs中,箱子每次移动要对人跑一边bfs,看看人能不能到达箱子移动的反方向(注意,人不能穿墙或者穿过箱子)
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 int px,py,bx,by; 5 int step; 6 }; 7 int dx[]={0,0,-1,1}; 8 int dy[]={1,-1,0,0}; 9 bool vis[10][10][5]; 10 bool fg[10][10]; 11 int mp[10][10]; 12 int n,m; 13 bool bfs(node fr,node to){ 14 memset(fg,0,sizeof(fg)); 15 queue<node> q; 16 q.push(fr); 17 while(!q.empty()){ 18 node u=q.front(); 19 q.pop(); 20 if(u.px==to.px && u.py==to.py) return true; 21 for(int i=0;i<4;++i){ 22 int xx=u.px+dx[i],yy=u.py+dy[i]; 23 if(xx<1 || xx>n || yy<1 || yy>m) continue; 24 if(fg[xx][yy]) continue; 25 if(mp[xx][yy]==1) continue; 26 if(xx==fr.bx && yy==fr.by) continue; 27 fg[xx][yy]=1; 28 node tem=u; 29 tem.px=xx;tem.py=yy; 30 q.push(tem); 31 } 32 } 33 return false; 34 } 35 int main(){ 36 int T;scanf("%d",&T); 37 for(int cas=1;cas<=T;++cas){ 38 scanf("%d%d",&n,&m); 39 memset(vis,0,sizeof(vis)); 40 node st; 41 st.step=0; 42 for(int i=1;i<=n;++i){ 43 for(int j=1;j<=m;++j){ 44 scanf("%d",&mp[i][j]); 45 if(mp[i][j]==4){ 46 st.px=i;st.py=j; 47 } 48 if(mp[i][j]==2){ 49 st.bx=i;st.by=j; 50 } 51 } 52 } 53 queue<node> Q; 54 Q.push(st); 55 int ans=0x3f3f3f3f; 56 while(!Q.empty()){ 57 node u=Q.front(); 58 Q.pop(); 59 if(mp[u.bx][u.by]==3){ 60 ans=min(ans,u.step); 61 } 62 //cerr<<u.bx<<' '<<u.by<<ans<<endl; 63 for(int i=0;i<4;++i){ 64 int bxx=u.bx+dx[i],byy=u.by+dy[i]; 65 int pxx=u.bx-dx[i],pyy=u.by-dy[i]; 66 if(bxx<1 || bxx >n || byy<1 || byy >m) continue; 67 if(vis[bxx][byy][i]) continue; 68 if(pxx<1 || pxx>n || pyy<1 || pyy>m) continue; 69 if(mp[bxx][byy]==1 || mp[pxx][pyy]==1) continue; 70 node box=u,peo=u; 71 peo.px=pxx;peo.py=pyy; 72 if(bfs(u,peo)){ 73 vis[bxx][byy][i]=1; 74 box.bx=bxx;box.by=byy; 75 box.px=u.bx;box.py=u.by; 76 box.step=u.step+1; 77 Q.push(box); 78 } 79 } 80 } 81 if(ans==0x3f3f3f3f) puts("-1"); 82 else printf("%d\n",ans); 83 } 84 return 0; 85 }
现在就六月份了,考前一个月用来复习了,也就是说打完这题,以及明天的训练赛,我就彻底不碰键盘一个月了。想想还是有点不舍得的。那么这题就当做是我的封建盘一个月的收山之作吧。哈哈哈哈。