poj 1475 Pushing Boxes(推箱子游戏,bfs+bfs)

算法思想:

对箱子进行bfs,每移动一次就 对人bfs一次,看能否走到箱子的后面,能走到就加入队列。

个人认为有点繁琐的地方就是路径的保存。

还有,每个case后有一个\n,不然会WA……

#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<stack>
using namespace std;
struct node
{
  int x,y;
  int px,py;
  int d;
};
int tx,ty;
int n,m;
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};

int ax[]={1,-1,0,0};
int ay[]={0,0,1,-1};

char word[]={'n','s','w','e'};
int cas;
char visb[25][25][4];
char visp[25][25];
stack<char> ans[10000];
int map[25][25];
int fa[10000];
int head,tail;
int pre[10000];
char path[10000];
bool okmap(int x,int y)
{
    return x>=0&&x<n&&y>=0&&y<m&&map[x][y];
}
bool okgo(int x,int y,int tarx,int tary,int dir)
{
    if(x==tarx&&y==tary)
    {
        ans[tail].push(word[dir]-32);
        return true;
    }
    queue<node> q;
    node front;
    front.px=x;
    front.py=y;
    q.push(front);
    node rear;
    pre[0]=-1;
    int f=0,e=1;
    while(!q.empty())
    {
        front=q.front();q.pop();
        for(int d=0;d<4;d++)
        {
            rear.px=front.px+dx[d];
            rear.py=front.py+dy[d];
            if(okmap(rear.px,rear.py)&&!visp[rear.px][rear.py])
            {
                visp[rear.px][rear.py]=1;
                pre[e]=f;
                path[e]=word[d];
                if(rear.px==tarx&&rear.py==tary)
                {
                    ans[tail].push(word[dir]-32);
                    while(e)
                    {
                        ans[tail].push(path[e]);
                        e=pre[e];
                    }

                    return true;
                }
                e++;
                q.push(rear);
            }
        }
        f++;
    }
    return false;
}
void print(int k)
{
    if(k==0) return;
    print(fa[k]);
    while(!ans[k].empty())
    {
        putchar(ans[k].top());
        ans[k].pop();
    }
}
void bfs(int x,int y,int px,int py)
{
    node front;
    front.x=x;front.px=px;
    front.y=y;front.py=py;
    queue<node> q;
    q.push(front);
    node rear;
    head=0,tail=1;
    while(!q.empty())
    {
        front=q.front();q.pop();
     //   printf("箱x=%d,y=%d人:x=%d,y=%d\n",front.x,front.y,front.px,front.py);
        for(int d=0;d<4;d++)
        {
            rear.x=front.x+dx[d];
            rear.y=front.y+dy[d];
            int lx=front.x+ax[d];   //反方向
            int ly=front.y+ay[d];

            if(okmap(rear.x,rear.y)&&okmap(lx,ly)&&!visb[rear.x][rear.y][d])
            {
              memset(visp,0,sizeof(visp));
                visp[front.x][front.y]=1;
                visp[front.px][front.py]=1;
                fa[tail]=head;
				
                if(okgo(front.px,front.py,lx,ly,d))
                {
					visb[rear.x][rear.y][d]=1;
                    rear.d=d;
                    rear.px=front.x;
                    rear.py=front.y;
                    if(rear.x==tx&&rear.y==ty)
                    {
                        print(tail);
                        return;
                    }
                    tail++;
                    q.push(rear);
                }
            }
        }
        head++;
    }
    printf("Impossible.");
}
int main()
{
    int bx,by,px,py;
    char a[30];
    cas=1;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(!n&&!m) break;
        memset(visb,0,sizeof(visb));
        memset(map,0,sizeof(map));

        for(int i=0;i<10000;i++)
            while(!ans[i].empty())
                ans[i].pop();

        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            for(int j=0;j<m;j++)
            {
                if(a[j]=='#') map[i][j]=0;
                else map[i][j]=1;
                if(a[j]=='T')
                {
                    tx=i;ty=j;
                }
                else if(a[j]=='B')
                {
                    bx=i;by=j;
                }
                else if(a[j]=='S')
                {
                    px=i;py=j;
                }
            }
        }
        printf("Maze #%d\n",cas++);
        bfs(bx,by,px,py);
        putchar(10);
        putchar(10);
    }
    return 0;
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TommyTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值