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 }