UVA-10384 The Wall Pushers (IDA*)
题目大意:走迷宫,遇到墙时可以推着墙走,但墙后还是墙时便不能推。求出一条任意的最短路径。
题目分析:这道题出的比较人性,输入的时候便是将四周的墙用二进制数表示好了,其实这样减轻了做题人的负担。IDA*,当到最近的一个出口的距离加上当前层数cur都比maxd大时,则剪枝。不过,值得注意的是:当推着墙走的时候,涉及到3个格子周围的墙的变化(在边界除外)。
代码如下:
# include<iostream> # include<cstdio> # include<cmath> # include<vector> # include<cstring> # include<algorithm> using namespace std; struct XY { int x,y; XY(int _x,int _y):x(_x),y(_y){} }; vector<XY>xy; int mp[4][6],sx,sy; int d[4][2]={{0,-1},{-1,0},{0,1},{1,0}}; int dd[4]={2,3,0,1}; string pd="WNES",ans; void f() { xy.clear(); for(int i=0;i<6;++i){ if((mp[0][i]&2)==0) xy.push_back(XY(0,i)); if((mp[3][i]&8)==0) xy.push_back(XY(3,i)); } for(int i=0;i<4;++i){ if((mp[i][0]&1)==0) xy.push_back(XY(i,0)); if((mp[i][5]&4)==0) xy.push_back(XY(i,5)); } } bool dfs(int cur,int maxd,int x,int y,string path) { if(cur==maxd){ if(x==0&&((mp[x][y]&2)==0)){ ans=path+'N'; return true; } if(x==3&&((mp[x][y]&8)==0)){ ans=path+'S'; return true; } if(y==0&&((mp[x][y]&1)==0)){ ans=path+'W'; return true; } if(y==5&&((mp[x][y]&4)==0)){ ans=path+'E'; return true; } return false; } f(); int minn=10000,l=xy.size(); for(int i=0;i<l;++i) minn=min(minn,abs(x-xy[i].x)+abs(y-xy[i].y)); if(cur+minn>maxd) return false; for(int i=0;i<4;++i){ int nx=x+d[i][0],ny=y+d[i][1]; if(nx<0||nx>3||ny<0||ny>5) continue; if(mp[x][y]&(1<<i)){ if(mp[nx][ny]&(1<<i)) continue; mp[x][y]^=(1<<i); mp[nx][ny]^=(1<<dd[i]); mp[nx][ny]^=(1<<i); int nnx=nx+d[i][0],nny=ny+d[i][1]; if(nnx>=0&&nnx<4&&nny>=0&&nny<6) mp[nnx][nny]^=(1<<dd[i]); if(dfs(cur+1,maxd,nx,ny,path+pd[i])) return true; mp[nx][ny]^=(1<<i); mp[nx][ny]^=(1<<dd[i]); mp[x][y]^=(1<<i); if(nnx>=0&&nnx<4&&nny>=0&&nny<6) mp[nnx][nny]^=(1<<dd[i]); }else{ if(dfs(cur+1,maxd,nx,ny,path+pd[i])) return true; } } return false; } int main() { //freopen("UVA-10384 The Wall Pushers.txt","r",stdin); while(scanf("%d%d",&sy,&sx)&&(sx+sy)) { --sx,--sy; for(int i=0;i<4;++i) for(int j=0;j<6;++j) scanf("%d",&mp[i][j]); for(int maxd=0;;++maxd){ if(dfs(0,maxd,sx,sy,"")){ cout<<ans<<endl; break; } } } return 0; }