POJ-1475:Pushing Boxes(嵌套bfs或bfs+A*算法)

来源:互联网 发布:红外图像处理算法 编辑:程序博客网 时间:2024/05/29 04:58


题目链接:点击打开链接


题目大意:

一个人要将箱子推到终点,输出推的最少次数的路径,若最少次数相同,输出步数最少。


解题思路:

刚上来没看清题目,以为就是步数最少,刷刷刷敲完发现样咧没过,但是我的代码结果比他还短,以为样例错了,神tm就交了一发,然后wa了。。。

后来仔细看了一下题目,原来是推的次数最少。想了一下,那么肯定要对箱子bfs,对箱子bfs的过程中对人的位置进行bfs,因为要推箱子的话,只有一个位置能推。那么对当前人的位置到这个位置bfs就好,实现稍微注意一下。还听说这道题是假特判,不清楚,反正我是没遇到啥问题。总体来说的话呢就是个嵌套bfs,但是不知道为啥,大佬做法跟我一样但是人家大佬是0msA的,我需要200+ms,可能是代码太过丑陋。。。

这题还有第二种做法,就是利用A星算法,A星算法其实最主要的就是确定优先级的问题。。。

这道题我想了一下,就把我第一次理解错题意的代码拿了出来,然后在struct 里面加上两个 关键字 push step 一个是推箱子次数,一个是总步数,手写好优先级,让推箱子次数少的在前面,如果次数相等就让步数少的在前面。再把队列改为优先队列,然后就A了Orz,但是用时1000+ms,可能是我写的问题,不过感觉这种方法确实没有嵌套bfs快。。。

以下贴两次的代码。。。

首先是嵌套bfs,时间200+ms


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_back#define hash hahausing namespace std;typedef long long ll;int n,m;bool vis[25][25][25][25];   //人箱状态bool v[25][25];         //对人单独bfs 人的状态char ma[25][25];int dx[4]={-1,1,0,0};int dy[4]={0,0,-1,1};int px,py,vx,vy,ex,ey;  //分别记录人箱子起始位置和终点string ans;struct nodes    //对人单独bfs用的struct{    int x,y;    string dir;};struct node     //箱子bfs{    int px,py,vx,vy;    string dir;};char vc(int i){    if(i==0)        return 'N';    if(i==1)        return 'S';    if(i==2)        return 'W';    return 'E';}char vs(int i){    if(i==0)        return 'n';    if(i==1)        return 's';    if(i==2)        return 'w';    return 'e';}bool check(int x,int y)     //检查点是否合理{    if(x>=1&&x<=n&&y>=1&&y<=m&&ma[x][y]!='#')        return 1;    return 0;}string bfs1(int sx,int sy,int kx,int ky,int gx,int gy)  //对人单独bfs 注意箱子也不能通过{    memset(v,0,sizeof(v));    queue<nodes> que;    nodes st;    st.x=sx;st.y=sy;    que.push(st);    v[st.x][st.y]=1;    string res="Impossible.";    nodes k1;    while(!que.empty())    {        nodes k=que.front();        que.pop();        if(k.x==kx&&k.y==ky)        {            res=k.dir;            break;        }        for(int i=0;i<4;i++)        {            int xx=k.x+dx[i];            int yy=k.y+dy[i];            if(check(xx,yy)&&v[xx][yy]==0&&(xx!=gx||yy!=gy))            {                k1.x=xx;                k1.y=yy;                k1.dir=k.dir+vs(i);                que.push(k1);                v[xx][yy]=1;            }        }    }    return res;}void bfs(){    memset(vis,0,sizeof(vis));    queue<node> que;    node st;    st.px=px;st.py=py;    st.vx=vx;st.vy=vy;    que.push(st);    vis[px][py][vx][vy]=1;  //记录初始位置    ans="Impossible.";    node k1;    while(!que.empty())    {        node k=que.front();        que.pop();        if(k.vx==ex&&k.vy==ey)        {            ans=k.dir;            break;        }        for(int i=0;i<4;i++)        {            int xx=k.vx+dx[i];   //判断箱子能否被人在后面推一格            int yy=k.vy+dy[i];            int bx=k.vx-dx[i];            int by=k.vy-dy[i];            if(check(xx,yy)&&check(bx,by)&&vis[k.vx][k.vy][xx][yy]==0)            {                string tem,re;                k1.px=k.vx;k1.py=k.vy;                k1.vx=xx;k1.vy=yy;                re=bfs1(k.px,k.py,bx,by,k.vx,k.vy);     //注意传箱子的位置                if(re==ans)     //人不能到达则跳过                    continue;                tem=k.dir+re;                k1.dir=tem+vc(i);                que.push(k1);                vis[k.vx][k.vy][xx][yy]=1;            }        }    }}int main(){    int kase=0;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                scanf(" %c",&ma[i][j]);                if(ma[i][j]=='S')                {                    px=i;                    py=j;                }                if(ma[i][j]=='B')                {                    vx=i;                    vy=j;                }                if(ma[i][j]=='T')                {                    ex=i;                    ey=j;                }            }        }        bfs();        printf("Maze #%d\n",++kase);        cout<<ans<<endl;        printf("\n");    }    return 0;}



A星算法,其实也就是正常bfs中加了关键字和优先队列。


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_back#define hash hahausing namespace std;typedef long long ll;int n,m;bool vis[25][25][25][25];   //记录状态char ma[25][25];        int dx[4]={0,-1,1,0};int dy[4]={1,0,0,-1};int px,py,vx,vy,ex,ey;string ans;struct node{    int px,py,vx,vy;    int push,step;      //分别为推箱子次数和总步数    string dir;    bool operator<(const node &g) const     //手写优先级将小的放在队列前面    {        if(push==g.push)            return step>g.step;        return push>g.push;    }};char vc(int i){    if(i==0)        return 'E';    if(i==1)        return 'N';    if(i==2)        return 'S';    return 'W';}char vs(int i){    if(i==0)        return 'e';    if(i==1)        return 'n';    if(i==2)        return 's';    return 'w';}void bfs(){    memset(vis,0,sizeof(vis));    priority_queue<node> que;   //使用优先队列    node st;    st.px=px;st.py=py;    st.vx=vx;st.vy=vy;    st.step=st.push=0;    que.push(st);    vis[px][py][vx][vy]=1;    ans="Impossible.";    node k1;    while(!que.empty())    {        node k=que.top();        que.pop();        if(k.vx==ex&&k.vy==ey)        {            ans=k.dir;            break;        }        for(int i=0;i<4;i++)        {            int xx=k.px+dx[i];            int yy=k.py+dy[i];            if(xx<1||xx>n||yy<1||yy>m||ma[xx][yy]=='#'||vis[xx][yy][k.vx][k.vy])                continue;            if(xx==k.vx&&yy==k.vy)  //如果人走的这一步推动了箱子            {                int tx=xx+dx[i];                int ty=yy+dy[i];                if(tx<1||tx>n||ty<1||ty>m||ma[tx][ty]=='#'||vis[xx][yy][tx][ty])                    continue;                k1.px=xx;k1.py=yy;                k1.vx=tx;k1.vy=ty;                k1.push=k.push+1;   //推箱子次数+1                k1.step=k.step+1;                k1.dir=k.dir+vc(i);                que.push(k1);                vis[xx][yy][tx][ty]=1;            }            else    //正常bfs            {                k1.px=xx;k1.py=yy;                k1.vx=k.vx;k1.vy=k.vy;                k1.push=k.push;                k1.step=k.step+1;                k1.dir=k.dir+vs(i);                que.push(k1);                vis[xx][yy][k.vx][k.vy]=1;            }        }    }}int main(){    int kase=0;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                scanf(" %c",&ma[i][j]);                if(ma[i][j]=='S')                {                    px=i;                    py=j;                }                if(ma[i][j]=='B')                {                    vx=i;                    vy=j;                }                if(ma[i][j]=='T')                {                    ex=i;                    ey=j;                }            }        }        bfs();        printf("Maze #%d\n",++kase);        cout<<ans<<endl;        printf("\n");    }    return 0;}



阅读全文
0 0
原创粉丝点击