http://acm.hdu.edu.cn/showproblem.php?pid=1813
IDA*。。。构造 h() 为所有点逃离迷宫的最少步数的最大值。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dir[4][2]={{0,1},{-1,0},{1,0},{0,-1}};
int maze[22][33];
struct S
{
bool a[33][22];
S() { memset(a,0,sizeof a); }
}s;
int n,dep,ans[222],dis[333][333];
struct P {int x,y;P(int a=0,int b=0){x=a,y=b;}};;
#include<queue>
void bfs(int x,int y)
{
queue<P> q;
dis[x][y]=0;
q.push(P(x,y));
while(!q.empty())
{
P u=q.front(); q.pop();
for(int d=0;d<4;d++)
{
P v(u.x+dir[d][0],u.y+dir[d][1]);
int x=v.x,y=v.y;
if(x<=0||x>=n-1||y<=0||y>=n-1||!maze[x][y]) continue;
if(dis[x][y]>dis[u.x][u.y]+1)
{
dis[v.x][v.y]=min(dis[v.x][v.y],dis[u.x][u.y]+1);
q.push(v);
}
}
}
}
bool h(int d,S s)
{
for(int i=1;i<n-1;i++)
for(int j=1;j<n-1;j++)
{
if(!s.a[i][j]) continue;
if(dis[i][j]+d>dep) return 0;
}
return 1;
}
bool dfs(int de,S u)
{
if(!h(de,u)) return 0;
if(de==dep) return 1;
for(int d=0;d<4;d++)
{
S v;
for(int i=1;i<n-1;i++)
for(int j=1;j<n-1;j++)
{
if(!maze[i][j]) continue;
int xx=i-dir[d][0], yy=j-dir[d][1];
v.a[i][j]=u.a[xx][yy];
xx=i+dir[d][0],yy=j+dir[d][1];
if(maze[xx][yy]) continue;
v.a[i][j]|=u.a[i][j];
}
ans[de]=d;
if(dfs(de+1,v)) return 1;
}
return 0;
}
int main()
{
bool ff=0;
while(cin>>n&&n)
{
string in[33];
for(int i=0;i<n;i++) cin>>in[i];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
maze[i][j]=(in[i][j]=='0');
if(i*j&&i<n-1&&j<n-1) s.a[i][j]=maze[i][j];
}
if(n<=2) { puts(""); continue; }
memset(dis,63,sizeof dis);
for(int i=0;i<n;i++)
{
if(maze[0][i]) bfs(0,i);
if(maze[i][0]) bfs(i,0);
if(maze[n-1][i]) bfs(n-1,i);
if(maze[i][n-1]) bfs(i,n-1);;
}
if(ff) puts(""); ff=1;
dep=0;
while(1) { if(dfs(0,s)) break; dep++; }
for(int i=0;i<dep;i++)
{
if(ans[i]==0) puts("east");
if(ans[i]==1) puts("north");
if(ans[i]==2) puts("south");
if(ans[i]==3) puts("west");
}
}
}