POJ 1475 Pushing Boxes(A*)

股价函数f(n)=g(n)+h(n),h(n)=0,g(n)为push和walk,push优先于walk。

在处理箱子和输出时很巧妙。

//
//  main.cpp
//  Richard
//
//  Created by 邵金杰 on 16/8/26.
//  Copyright © 2016年 邵金杰. All rights reserved.
//


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=20+2;
int best[maxn][maxn][maxn][maxn][2];
char dir[5]="SENW";
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
char map[maxn][maxn];
int n,m;
struct node{
    int boxrow,boxcol,manrow,mancol,push,walk;
    bool operator < (const node &e) const {
        if(push!=e.push) return push>e.push;
        return walk>e.walk;
    }
    void show()const{
        printf("box@(%d,%d)  man@(%d,%d)  push:%d  walk:%d\n",
               boxrow, boxcol, manrow, mancol, push, walk);
    }
};
void setbest(struct node &state)
{
    int *a=best[state.boxrow][state.boxcol][state.manrow][state.mancol];
    a[0]=state.push;
    a[1]=state.walk;
}
bool is_reach(int x,int y)
{
    return x<1||x>n||y<1||y>m||map[x][y]=='#';
}
bool is_best(struct node &state)
{
    int *a=best[state.boxrow][state.boxcol][state.manrow][state.mancol];
    if(a[0]!=state.push) return a[0]>state.push;
    return a[1]>state.walk;
}
void print(int br,int bc,int mr,int mc,int push,int walk)
{
    if(push==0&&walk==0) return ;
    for(int i=0;i<4;i++)
    {
        int pmr=mr+dx[i];
        int pmc=mc+dy[i];
        if(is_reach(pmr,pmc)) continue;
        if(!(pmr==br&&pmc==bc)&&best[br][bc][pmr][pmc][0]==push&&best[br][bc][pmr][pmc][1]==walk-1)
        {
            print(br,bc,pmr,pmc,push,walk-1);
            printf("%c",tolower(dir[i]));
            break;
        }
        int pbr=br+dx[i];
        int pbc=bc+dy[i];
        if(is_reach(pbr,pbc)) continue;
        if(pbr==mr&&pbc==mc&&best[pbr][pbc][pmr][pmc][0]==push-1&&best[pbr][pbc][pmr][pmc][1]==walk)
        {
            print(pbr,pbc,pmr,pmc,push-1,walk);
            printf("%c",dir[i]);
            break;
        }
    }
}
void Astar()
{
    memset(best,0x6f,sizeof(best));
    node state;
    char *p;
    for(int i=1;i<=n;i++)
    {
        p=strchr(map[i]+1,'S');
        if(p)
        {
            state.manrow=i;
            state.mancol=(int)(p-(map[i]));
        }
        p=strchr(map[i]+1,'B');
        if(p)
        {
            state.boxrow=i;
            state.boxcol=(int)(p-(map[i]));
        }
    }
    state.push=state.walk=0;
    setbest(state);
    priority_queue<node> pq;
    pq.push(state);
    node now,next;
    while(!pq.empty())
    {
        now=pq.top();
        pq.pop();
        if(map[now.boxrow][now.boxcol]=='T')
        {
            print(now.boxrow,now.boxcol,now.manrow,now.mancol,now.push,now.walk);
            printf("\n");
            return ;
        }
        for(int i=0;i<4;i++)
        {
            next=now;
            next.manrow+=dx[i];
            next.mancol+=dy[i];
            if(is_reach(next.manrow,next.mancol)) continue;
            if(next.manrow==now.boxrow&&next.mancol==now.boxcol)
            {
                next.boxrow+=dx[i];
                next.boxcol+=dy[i];
                if(is_reach(next.boxrow,next.boxcol)) continue;
                ++next.push;
                if(!is_best(next)) continue;
                pq.push(next);setbest(next);
            }
            else
            {
                ++next.walk;
                if(!is_best(next)) continue;
                pq.push(next);setbest(next);
            }
        }
    }
    printf("Impossible.\n");
}
int main()
{
    int kase=0;
    while(scanf("%d%d",&n,&m)&&(n+m))
    {
        for(int i=1;i<=n;i++)
            scanf("%s",map[i]+1);
        printf("Maze #%d\n",++kase);
        Astar();
        printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值