股价函数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;
}