传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1813
题意:给你一个n*n的迷宫,其中0代表有一个人在这个位置,1代表墙,现在要求一个路线,使所有的人通过这个路线都可以走到迷宫的边界
注意当到达边界就相当于出去了不用继续走了,一个格子可以容纳很多人。
题解:先用BFS求出迷宫内部的点走到边界的最小步数(为了后面的IDA*剪枝),因为有很多状态,不好表示,所以可以想到用IDA*算法,在dfs的时候每次内部的点安同一个方向走,当某个点走到边界或遇见墙时不变,其他的点还是继续走。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <deque> #include <queue> #include <iterator> #include <stack> #include <map> #include <set> #include <algorithm> #include <cctype> using namespace std; #define si1(a) scanf("%d",&a) #define si2(a,b) scanf("%d%d",&a,&b) #define sd1(a) scanf("%lf",&a) #define sd2(a,b) scanf("%lf%lf",&a,&b) #define ss1(s) scanf("%s",s) #define pi1(a) printf("%d\n",a) #define pi2(a,b) printf("%d %d\n",a,b) #define mset(a,b) memset(a,b,sizeof(a)) #define forb(i,a,b) for(int i=a;i<b;i++) #define ford(i,a,b) for(int i=a;i<=b;i++) typedef long long LL; const int N=11; const int INF=0x3f3f3f3f; const double PI=acos(-1.0); const double eps=1e-7; int n,depth; int cnt;//表示不是边界点的个数 int x[101],y[101];//存放不是边界的点 int xh[N][N];//xh[i][j]表示ij到边界的最短距离,由BFS生成 char str[N][N]; int ans[1000];//存放方向 int dir[4][2]={0,1,-1,0,1,0,0,-1};//east north south west 按照字典序 bool flag; struct node { int x,y; }w,e; bool bianjie(int x,int y) { if(x==0||x==n-1||y==0||y==n-1) return true; return false; } bool inmap(int x,int y) { if(x>=0&&x<n&&y>=0&&y<n) return true; return false; } void bfs() { queue<node> q; q.push(w); xh[w.x][w.y]=0; while(!q.empty()) { e=q.front(); q.pop(); for(int i=0;i<4;i++) { w.x=e.x+dir[i][0]; w.y=e.y+dir[i][1]; if(inmap(w.x,w.y)&&str[w.x][w.y]=='0') { if(xh[w.x][w.y]<=xh[e.x][e.y]) continue; xh[w.x][w.y]=xh[e.x][e.y]+1; q.push(w); } } } } int geth(int x[],int y[])//统计最大的距离 { int ss=0; forb(i,0,cnt) ss=max(ss,xh[x[i]][y[i]]); return ss; } void dfs(int tx[],int ty[],int de) { if(flag) return ; if(geth(tx,ty)>de) return ; if(de==0)//或者geth(tx,ty)==0 { flag=true; return ; } for(int i=0;i<4;i++) { int xx[101],yy[101]; for(int j=0;j<cnt;j++)//不是边界的点都按照i这个方向走 { xx[j]=tx[j]; yy[j]=ty[j]; if(bianjie(xx[j],yy[j])) continue; if(str[xx[j]+dir[i][0]][yy[j]+dir[i][1]]=='0') { xx[j]+=dir[i][0]; yy[j]+=dir[i][1]; } } ans[de]=i; dfs(xx,yy,de-1); if(flag) return;//这个地方一定要加上这一句,不然会被覆盖 } } void IDA() { flag=false; depth=geth(x,y); while(1) { dfs(x,y,depth); if(flag) { for(int i=depth;i>0;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"); } break; } depth++; } } int main() { // freopen("input.txt","r",stdin); int ca=0; while(~si1(n)) { forb(i,0,n) ss1(str[i]); mset(xh,INF);//初始化为无穷大 cnt=0; forb(i,0,n) forb(j,0,n) if(str[i][j]=='0') { w.x=i; w.y=j; if(!bianjie(i,j)) { x[cnt]=i; y[cnt]=j; cnt++; } else bfs();//求出每个点要走出去的最小步数 } if(ca++) printf("\n"); if(cnt==0||geth(x,y)==INF) {continue;}//都是边界点|走不出去的情况 IDA(); } return 0 ; }