poj1475 -- Pushing Boxes

 

這道題其實挺有趣 的,這讓我想起小時候諾基亞手機上的推箱子游戲(雖然一點也很差玩)node

(英文很差-->)  題意翻譯:ios

  初始人(S),箱子(B),目的地(T)用人把箱子推到 T最小步數及其路徑(知足最小步數的任何一條均可),若是不可行輸出「Impossible."數組

思路:spa

  咱們能夠把這看成一次遊戲,過程在於人推箱子,使箱子到終點並儘可能快(步數小)。翻譯

因而——咱們能想到:重點是箱子【人只是個輔助】code

因此咱們先利用bfs搜索最短迷宮路徑的方式,找到箱子所到達最短路徑,中間穿插 人到能推箱子的地方的最短路徑bfsblog

最後一個問題:怎麼輸出路徑?隊列

不要怕!!!在隊列中維護string類型的路徑【用結構體】。(還有一些小問題,本身去好好想一想吧)遊戲

而後就很簡單吶 ^_^字符串

.......

可我調了一個晚上+一個上午,細節要注意,代碼有點長,以下:

//bfs嵌套 
#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<iostream>
using namespace std;
const int N=25;
int n,m,t=0;
int dx[5]={0,-1,1,0},tx,ty,bbx,by;
int dy[5]={1,0,0,-1};
char ls[5]={'e','n','s','w'},bs[5]={'E','N','S','W'};        //這個能方便在最後輸出路徑時,讓方位數組與東南西北所對應 
char a[N][N];
struct node {    //bfs_person隊列存的結構體 
    int x,y; string s;
}pers;
struct boxx {        //bfs_box隊列所存的結構體 
    int x,y,xr,yr; string s;
}bx;
queue<node> q;
queue<boxx> Q;
bool fw_ok(int p,int q) {    //輔助pd範圍的 
    if(p<1||q<1||p>n||q>m) return false;
    return true;
}
bool vis1[N][N],vis2[N][N];
bool bfs_person(int sx,int sy,int rx,int ry,int xzx,int xzy) {        //出發點,要到達點,箱子位置 
    memset(vis1,0,sizeof(vis1));
    vis1[sx][sy]=1; vis1[xzx][xzy]=1;    //注意,人不能夠站在箱子上吧 
    while(!q.empty()) q.pop();        //清零操做(多組數據) 
    node k; k.x=sx; k.y=sy; k.s="";
    q.push(k);
    while(!q.empty()) {
        pers=q.front();    q.pop();    //這個pers是個全局變量,結束時存下了人走的路徑,以便 bfs_box記錄路徑 
        if(pers.x==rx&&pers.y==ry) return true;
        for(int i=0;i<4;i++) {
            int xx=pers.x+dx[i],yy=pers.y+dy[i];
            if(fw_ok(xx,yy)&&a[xx][yy]!='#'&&!vis1[xx][yy]) {
                vis1[xx][yy]=1;
                node p; p.x=xx; p.y=yy; p.s=pers.s+ls[i];        //string的特性[+直接將另外一個字符串拼接在一塊兒] 
                q.push(p);
            }
        }
    }
    return false;    //到不了 
}
bool bfs_box() {    //同理 
    memset(vis2,0,sizeof(vis2));
    while(!Q.empty()) Q.pop();
    boxx k; k.x=bbx; k.y=by; k.xr=tx; k.yr=ty; k.s="";
    Q.push(k); vis2[bbx][by]=true;
    while(!Q.empty()) {
        bx=Q.front();    Q.pop();
        if(a[bx.x][bx.y]=='T') {
            cout<<bx.s<<endl;
            return true;
        }
        for(int i=0;i<4;i++) {        //箱子所去方位(重要) 
            int xx=bx.x+dx[i],yy=bx.y+dy[i];
            if(fw_ok(xx,yy)&&a[xx][yy]!='#'&&!vis2[xx][yy]) {
                bool flag=bfs_person(bx.xr,bx.yr,bx.x-dx[i],bx.y-dy[i],bx.x,bx.y);    
                    //想想人要站在哪裏才能按(dx[i],dy[i])方向推箱子:人確定是在箱子所去方位的反方向一格(減法)[可能表達不清,本身理解一下]
                if(flag) {        //有可能人到不了推箱子的地方,這樣就不可行了 
                    vis2[xx][yy]=1;
                    boxx p; p.xr=bx.x,p.yr=bx.y,p.x=xx,p.y=yy; p.s=bx.s+pers.s+bs[i];        //這裏理解了pers是全局變量的意義吧 
                    Q.push(p); 
                }
            }
        }
    }
    return false;
}
int main() {
//    freopen("poj1475.out","w",stdout);
    while(1) {
        scanf("%d%d",&n,&m);
        if(!n&&!m) break;
        for(int i=1;i<=n;i++) {
            scanf("%s",a[i]+1);
        }
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=m;j++) {
                if(a[i][j]=='S') { tx=i,ty=j; }
                else if(a[i][j]=='B') { bbx=i,by=j; }
            }
        }
        printf("Maze #%d\n",++t);
        bool flag=bfs_box();
        if(!flag) printf("Impossible.\n");
        cout<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索