Pushing Boxes(廣度優先搜索)

題目傳送門node

首先說明我這個代碼和lyd的有點不一樣:可能更加複雜ios

 既然要求以箱子步數爲第一關鍵字,人的步數爲第二關鍵字,那麼咱們能夠想先找到箱子的最短路徑。但單單找到箱子的最短路確定不行啊,由於有時候不能被推進,怎樣肯定一條既知足最短又知足可行的箱子路徑呢,其實這就是一種有限制的BFS數組

 對於箱子:spa

  設如今的位置爲x,y,擴展方向爲dx,dy,將要到達的下一個位置爲x+dx,y+dycode

 check它是否可行:blog

1.不越界。ci

2.以前沒有走過。get

3.不能走到「#」上。string

4.人可以從當前站立的位置到達(x-dx,y-dy)。it

誒,對了,第4個條件實際上就是對於人的bfs。


 

  所以,這就是一個雙重bfs。(數據範圍r,c<=20可行!)

  那麼對於人的bfs,有什麼限制條件:固然最重要的不能走到箱子如今的位置(x,y)上

  還有記錄路徑,每次回溯和逆推。

  嗯,具體細節看代碼吧(不想打字了)

 

//Pushing Boxes -POJ1475 //最長代碼 祭 AC 329ms //開始沒有數組清零WA //而後數組開大了,TLE 
#include<cstring> #include<algorithm> #include<iostream> #include<cstdio> #include<queue>
#define de system("pause");
#define re register int
using namespace std; int r,c,ans,ansx,ansy; char s[50][50]; int per[5],box[5]; int dx[]={-1,1,0,0}; int dy[]={0,0,-1,1}; char ren[]={'n','s','w','e'}; char xiang[]={'N','S','W','E'}; bool bz[30][30],flag[30][30]; struct node{ int x,y,step; int man[3]; node(int xx,int yy,int stepp,int mx,int my) { x=xx,y=yy,step=stepp; man[1]=mx,man[2]=my; } }; struct node2{ int x,y; node2(int xx,int yy) { x=xx; y=yy; } }; queue<node> q; queue<node2> p; struct hp{ int px,py,d; int cnt; int path[500]; }fix[30][30],walk[30][30];
//fix主要記錄箱子的路徑,walk主要記錄人的路徑。 inline
bool bfs(int bx,int by,int aimx,int aimy,int nowx,int nowy) { memset(flag,0,sizeof flag); memset(walk,0,sizeof walk); while(p.size()) p.pop(); p.push(node2(nowx,nowy)); if(nowx==aimx&&nowy==aimy) return 1; flag[nowx][nowy]=1; while(!p.empty()) { node2 now=p.front(); int x=now.x,y=now.y; p.pop(); for(re i=0;i<=3;++i) { int cx=x+dx[i],cy=y+dy[i]; if(cx<1||cx>r||cy<1||cy>c)continue; if(flag[cx][cy])continue; if(s[cx][cy]=='#')continue; if(cx==bx&&cy==by)continue; p.push(node2(cx,cy)); flag[cx][cy]=1; walk[cx][cy].px=x; walk[cx][cy].py=y; walk[cx][cy].d=i; if(cx==aimx&&cy==aimy) { return 1; } } } return 0; } inline bool check(int x,int t1,int y,int t2,int standx,int standy) { if(x+t1<1||x+t1>r||y+t2<1||y+t2>c)return 0; if(bz[x+t1][y+t2]) return 0; if(s[x+t1][y+t2]=='#')return 0; if(bfs(x,y,x-t1,y-t2,standx,standy))//若是人可以移動 { int tx=x-t1,ty=y-t2;//從目標回溯到初位置 while(tx!=standx||ty!=standy) { hp temp=walk[tx][ty]; fix[x+t1][y+t2].path[++fix[x+t1][y+t2].cnt]=walk[tx][ty].d; tx=temp.px; ty=temp.py; }//在這裏順便就把這一次轉移路徑記錄下來 return 1; } return 0; } inline void Bfs() { while(!q.empty()) { node now=q.front(); int x=now.x,y=now.y,step=now.step; int man_x=now.man[1],man_y=now.man[2]; q.pop(); for(re i=0;i<=3;++i) { int cx=x+dx[i],cy=y+dy[i]; if(check(x,dx[i],y,dy[i],man_x,man_y)) { q.push(node(cx,cy,step+1,x,y)); bz[cx][cy]=1; fix[cx][cy].px=x,fix[cx][cy].py=y; fix[cx][cy].d=i; if(s[cx][cy]=='T') { if(step+1<ans) { ans=step+1; ansx=cx,ansy=cy; } } } } } } char shuchu[600]; int rt=0; inline void print() { int num=0; int prx=ansx; int pry=ansy; int tt=0; while((prx!=box[1])||(pry!=box[2])) { hp ne=fix[prx][pry]; shuchu[++num]=xiang[ne.d]; for(re i=1;i<=ne.cnt;++i) { shuchu[++num]=ren[ne.path[i]]; } prx=ne.px; pry=ne.py; } printf("Maze #%d\n",++rt); for(re i=num;i>=1;--i) cout<<shuchu[i]; puts(""); } int main() { while(1) { while(q.size())q.pop(); memset(bz,0,sizeof bz); // memset(shuchu,0,sizeof shuchu); memset(fix,0,sizeof fix); // memset(walk,0,sizeof walk); ans=1e6; scanf("%d%d",&r,&c); if(r==0&&c==0)break; for(re i=1;i<=r;++i){ scanf("%s",s[i]+1); for(re j=1;j<=c;++j){ if(s[i][j]=='B')box[1]=i,box[2]=j,bz[i][j]=1; if(s[i][j]=='S')per[1]=i,per[2]=j; } } q.push(node(box[1],box[2],0,per[1],per[2])); Bfs(); if(ans==1e6) { printf("Maze #%d\n",++rt); puts("Impossible."); } else print(); puts(""); } return 0; }

Add/ 

1.關於POJ的special judge可能有點毒瘤,因此建議按照'N','S','W','E'的方向進行搜索。

2.數組不要開大了。

3.輸出兩個換行......

相關文章
相關標籤/搜索