POJ1475 Pushing Boxes(双搜索)

POJ1475 Pushing Boxes

 推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点

本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化人移动的步数。若仍有多条路线,则按照N、S、W、E的顺序优先选择箱子的移动方向(即先上下推,再左右推)。在此前提下,再按照n、s、w、e的顺序优先选择人的移动方向(即先上下动,再左右动)。

 

  • 每个阶段的状态包括人的位置,箱子的位置,由于每次在移动箱子之后,人的位置一定位于箱子之前的位置,所以可以将每次箱子刚刚移动后,箱子与人的位置的状态打包在一起,bfs中对于取出的队头,枚举箱子的下一个位置,然后再用一个bfs求出人由现在的位置到应该在的位置的最短步数即可
  • Impossible后面没打'.',调了一上午qwq
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cctype>
  5 #include <queue>
  6 #include <iostream>
  7 #include <cmath>
  8 using namespace std;
  9 
 10 #define N 26
 11 #define res int
 12 #define inf 0x3f3f3f3f
 13 
 14 const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
 15 const char A[4]={'N','S','W','E'},B[4]={'n','s','w','e'};
 16 int n,m;
 17 char s[50][50];
 18 
 19 string tmp;
 20 struct node {
 21     int x,y,px,py;
 22     string ans;
 23 };
 24 
 25 inline bool valid(int x,int y){
 26     return (x>=1 && x<=n && y>=1 && y<=m && s[x][y]!='#');
 27 }
 28 
 29 bool bfs2(node a,node b)
 30 {
 31     tmp="";
 32     node st; 
 33     st.x=a.px; 
 34     st.y=a.py; 
 35     st.ans="";//人的初始位置
 36     queue<node> q;
 37     q.push(st);
 38     bool v[26][26];
 39     memset(v,0,sizeof(v));
 40     while(q.size()) 
 41     {
 42         node now=q.front(); q.pop();
 43         if(now.x==a.x && now.y==a.y) 
 44         { tmp=now.ans; return true; }
 45         for(res k=0 ; k<4 ; k++)
 46         {
 47             node nxt; 
 48             nxt.x=now.x+dx[k]; 
 49             nxt.y=now.y+dy[k];
 50             if(!valid(nxt.x,nxt.y)||v[nxt.x][nxt.y]) continue;
 51             if(nxt.x==b.x && nxt.y==b.y) continue;
 52             v[nxt.x][nxt.y]=1;
 53             nxt.ans=now.ans+B[k];
 54             q.push(nxt);
 55         }
 56     }
 57     return false;
 58 }
 59 node st; 
 60 string bfs1()
 61 {
 62     st.x=st.y=st.px=st.py=-1; 
 63     st.ans="";
 64     for(res i=1 ; i<=n ; i++)
 65         for(res j=1 ; j<=m ; j++)
 66             if(s[i][j]=='B')
 67                 st.x=i,st.y=j,s[i][j]='.';
 68             else if(s[i][j]=='S')
 69                 st.px=i,st.py=j,s[i][j]='.';                
 70     queue<node> q;
 71     int v[25][25][4];
 72     memset(v,0,sizeof(v));
 73     q.push(st);
 74     string ans="Impossible.";
 75     int cnt_box=inf,cnt_man=inf;
 76     while(q.size())
 77     {
 78         node now=q.front(); q.pop();
 79         if(s[now.x][now.y]=='T')
 80         {
 81             int cntb(0);
 82             for(res i=1 ; i<now.ans.length() ; i++)
 83                 if(now.ans[i]>'A' && now.ans[i]<'Z') cntb++;
 84             if(cntb<cnt_box || (cntb==cnt_box&& now.ans.length()-cntb<cnt_man))
 85                 cnt_box=cntb,cnt_man=now.ans.length()-cntb,ans=now.ans;
 86             continue;
 87         }
 88         for(res k=0 ; k<4 ; k++)
 89         {
 90             node nxt; nxt.x=now.x+dx[k]; nxt.y=now.y+dy[k];
 91             if(!valid(nxt.x,nxt.y) || v[nxt.x][nxt.y][k]) continue;
 92             
 93             node pre=now;
 94             if(k==3) pre.y=now.y-1;
 95             else if(k==2) pre.y=now.y+1;
 96             else if(k==1) pre.x=now.x-1;
 97             else pre.x=now.x+1;//人的移动,此处x,y表示目标位置 
 98             v[nxt.x][nxt.y][k]=1;
 99             if(!valid(pre.x,pre.y) || !bfs2(pre,now)) continue;
100             nxt.ans=now.ans+tmp;
101             nxt.ans+=A[k];
102             nxt.px=now.x; 
103             nxt.py=now.y;
104             q.push(nxt);
105         }
106     }
107     return ans;
108 }
109 
110 int main()
111 {
112     int Case(0);
113     while(scanf("%d %d",&n,&m)&&n&&m)
114     {
115         Case++;
116         for(res i=1 ; i<=n ; i++) cin>>(s[i]+1);
117         cout<<"Maze #"<<Case<<endl;
118         cout<<bfs1()<<endl<<endl;
119     }
120     return 0;
121 }
View Code

 

posted @ 2019-02-16 11:10  孑行  阅读(144)  评论(0编辑  收藏  举报