傳送門:https://vjudge.net/problem/HDU-1254node
題意:就是一個箱子的推箱子,問箱子最少走多少步到達目的地。ios
由於我c++實訓打算寫個推箱子游戲,看見有這題就過來打一下。。。。c++
這題兩種解法ide
第一種:就是普通的bfs,只是記錄狀態有四個值,分別是人的座標和箱子的座標,因爲n很小,因此vis[n][n][n][n]內存仍是能夠接受的。spa
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,看看人能不能到達箱子移動的反方向(注意,人不能穿牆或者穿過箱子).net
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 }
如今就六月份了,考前一個月用來複習了,也就是說打完這題,以及明天的訓練賽,我就完全不碰鍵盤一個月了。想一想仍是有點不捨得的。那麼這題就當作是個人封建盤一個月的收山之做吧。哈哈哈哈。code