Pushing Boxes(广度优先搜索)

Posted 719666a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pushing Boxes(广度优先搜索)相关的知识,希望对你有一定的参考价值。

题目传送门

首先说明我这个代码和lyd的有点不同:可能更加复杂

既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径。但单单找到箱子的最短路肯定不行啊,因为有时候不能被推动,怎样确定一条既满足最短又满足可行的箱子路径呢,其实这就是一种有限制的BFS。

对于箱子:

设现在的位置为x,y,扩展方向为dx,dy,将要到达的下一个位置为x+dx,y+dy

check它是否可行:

1.不越界。

2.之前没有走过。

3.不能走到“#”上。

4.人能够从当前站立的位置到达(x-dx,y-dy)。

诶,对了,第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];
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
",++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
",++rt);
            puts("Impossible.");
        }
        else print();
        puts(""); 
    }
    return 0;
}

 

 

 

 

 

以上是关于Pushing Boxes(广度优先搜索)的主要内容,如果未能解决你的问题,请参考以下文章

POJ - 1475 Pushing Boxes

poj1475 Pushing Boxes[双重BFS(毒瘤搜索题)]

POJ 1475 Pushing Boxes

POJ-1475-Pushing Boxes(BFS)

pushing boxes

[poj P1475] Pushing Boxes