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 }
View Code

第二种:第二种解法是在网上学来的。因为箱子最少步,所以肯定是对箱子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 }
View Code

现在就六月份了,考前一个月用来复习了,也就是说打完这题,以及明天的训练赛,我就彻底不碰键盘一个月了。想想还是有点不舍得的。那么这题就当做是我的封建盘一个月的收山之作吧。哈哈哈哈。

 

posted @ 2019-06-01 17:04  小布鞋  阅读(711)  评论(0编辑  收藏  举报