POJ 1475 Pushing Boxes 【A*bfs套bfs】


点击打开链接


题意:


推箱子,这游戏都玩过吧,没玩过也知道规则吧。

现在就问你把箱子推到指定位置,的最优情况。

这里的最优是:

1.推箱子的次数最少,

2.推箱子次数相同,走的次数最少。

找到该最优解并把路径打出来,推这箱子的移动用大写字母表示,自己走的用小写字母表示。



题解:

bfs套bfs

先搜箱子走的状态,然后搜该状态下人能否到达,

我自己写了一个曼哈顿估值,,,,还是跑了235ms 应该是快了点吧,,,可能是写了假的Astar。。。


#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

int dir[4][2]={-1,0, 1,0, 0,-1, 0,1};/*上下左右*/
char d1[5]="NSWE";
char d2[5]="nswe";
int n,m,d;
char ma[22][22];
int vis[22][22][4];
int vv[22][22];
struct node{
    int bx,by;
    int px,py;
    int push,walk;
    int fp;
    string way;
    bool operator <(const node t)const{
        if(t.fp==fp) return walk>t.walk;
        return fp>t.fp;
    }
}st,ed,box,u,v;
struct nod{
    int x,y;
    int g,f;
    int fx,fy;
    string way;
    bool operator<(const nod t)const{
        return t.f<f;
    }
}sp,up,vp,pre;
priority_queue<node>que;
priority_queue<nod>qq;
int get_f(node b,int a){
    int ret=abs(b.bx-ed.bx)+abs(b.by-ed.by);
    return ret+a;
}
int bfs(int sx,int sy,int ex,int ey){
    vp.way="";vp.g=0;
    if(sx==ex&&sy==ey) return 1;
    memset(vv,0,sizeof(vv));
    while(!qq.empty()) qq.pop();
    sp.x=sx,sp.y=sy;
    sp.g=0;
    sp.way="";
    vv[sx][sy]=1;
    sp.f=abs(sx-ex)+abs(sy-ey);
    qq.push(sp);
    while(!qq.empty()){
        up=qq.top();
        qq.pop();
        //printf("  pre(%d,%d)->%d\n",up.x,up.y,up.g);
        for(int i=0;i<4;++i){
            int tx=up.x+dir[i][0];
            int ty=up.y+dir[i][1];
            if(tx<1||tx>n||ty<1||ty>m) continue;
            //if(sx==6&&sy==4) printf("(%d,%d)-%c %d \n",tx,ty,ma[tx][ty],vv[tx][ty]);
            if(ma[tx][ty]=='#'||vv[tx][ty]) continue;
            vp.x=tx,vp.y=ty;
            vp.g=up.g+1;
            vp.way=up.way+d2[i];
            vp.fx=up.x,vp.fy=up.y;
            if(tx==ex&&ty==ey) return 2;
            vp.f=vp.g+abs(tx-ex)+abs(ty-ey);
            vv[tx][ty]=1;
            qq.push(vp);
        }
    }
    return 0;
}

int Astar(){
    int flag;
    memset(vis,0,sizeof(vis));
    while(!que.empty()) que.pop();
    st.bx=box.bx;
    st.by=box.by;
    st.px=pre.x;
    st.py=pre.y;
    st.push=st.walk=0;
    st.fp=get_f(st,0);
    que.push(st);
    while(!que.empty()){
        u=que.top();
        que.pop();
        if(u.bx==ed.bx&&u.by==ed.by){
            cout<<u.way<<endl;
            return 1;
        }
        for(int i=0; i<4; ++i){
            int tx=u.bx+dir[i][0];
            int ty=u.by+dir[i][1];
            if(tx<1||tx>n||ty<1||ty>m||ma[tx][ty]=='#'||vis[tx][ty][i]) continue;
            //if(u.bx==4&&u.by==2)printf("box(%d,%d)->%c, %d,%d   pre(%d,%d)->%d----%d\n",u.bx,u.by,ma[tx][ty],tx,ty,u.px,u.py,vis[tx][ty][i],flag);

            if(i<2) d=!i;
            else if(i==2) d=3;
            else d=2;

            ma[u.bx][u.by]='#';
//            if(u.bx==4&&u.by==2)
//            for(int ii=1;ii<=7;++ii){
//                for(int jj=1;jj<=11;++jj){
//                    printf("%c ",ma[ii][jj]);
//                }puts("");
//            }
            flag=bfs(u.px,u.py,u.bx+dir[d][0],u.by+dir[d][1]);
            if(flag){
                if(vis[u.bx][u.by][i]) {
                    ma[u.bx][u.by]='.';
                    continue;
                }//if(u.bx==4&&u.by==2) printf("u.p->(%d %d) u.b->(%d,%d)\n",u.px,u.py,u.bx+dir[d][0],u.by+dir[d][1]);
                vis[u.bx][u.by][i]=1;
                v.bx=tx,v.by=ty;
                v.px=u.bx;v.py=u.by;
                v.push=u.push+1;
                v.walk=u.walk+vp.g;
                v.way=u.way;
                if(flag==1) v.way+=d1[i];
                else {
                    v.way+=vp.way;
                    v.way+=d1[i];
                }
                v.fp=get_f(v,v.push);
                que.push(v);
            }

            ma[u.bx][u.by]='.';

        }
    }
    return 0;
}
int main(){
	int ca = 0;
	while(scanf("%d%d", &n, &m)&&(n+m)){

		for(int i=1; i<=n; ++i) scanf("%s",ma[i]+1);
		for(int i=1; i<=n; ++i)
            for(int j=1; j<=m; ++j){
                if(ma[i][j]=='S'){
                    ma[i][j]='.';
                    pre.x=i,pre.y=j;
                }
                if(ma[i][j]=='T'){
                    ma[i][j]='.';
                    ed.bx=i,ed.by=j;
                }
                if(ma[i][j]=='B'){
                    ma[i][j]='.';
                    box.bx=i,box.by=j;
                }
            }
        printf("Maze #%d\n", ++ca);
        if(Astar()) ;
        else puts("Impossible.");
        puts("");

	}
	return 0;
}
/*
8 9
#########
#......T#
#.S.....#
##B######
#.......#
#.......#
#.......#
#########
*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值