hdu 3309 广搜
题意:两个球,两个目标点,每次同时向 上下左右 移动这两个球,若前面是墙,则不动,两球不能重合,若一球到达目标点,另一球可从那里经过。。问最少多少步能将两球移动到目标点。
分析:广搜,用四维数组f[x][y][u][v]记录两球坐标分别为x y , u v 时的最少步数。注意两球要同时移动,且不能重合,但一球在目标点,另一球可以与它重合。
int dx[] = {-1,0,1,0};//up Right down Left int dy[] = {0,1,0,-1}; const int M = 25; const int N = 100005; int n,m,ans; char c[M][M];//地图 int x[N],y[N],u[N],v[N],p,q;//坐标数组 int xx,yy,uu,vv; int f[M][M][M][M];//判重 void readdata(){ memset(f,5,sizeof f); xx=yy=uu=vv=-1; cin>>n>>m; FOR(i,0,n) { cin>>c[i]; FOR(j,0,m) if(c[i][j]=='B') { if(xx==-1) xx=i,yy=j; else uu=i,vv=j; } } } void bfs(){ ans=-1; p=q=0; x[p]=xx; y[p]=yy; u[p]=uu; v[p]=vv; p++; f[xx][yy][uu][vv]=f[uu][vv][xx][yy]=0; while(p>q){ int t = q++; FOR(i, 0, 4){ xx=x[t]+dx[i]; yy=y[t]+dy[i]; uu=u[t]+dx[i]; vv=v[t]+dy[i]; int x1=xx ,y1=yy, u1=uu, v1=vv; /* if(c[xx][yy] == '*' ) x1=x[t], y1=y[t]; else if(xx==u[t]&&yy==v[t]){ if(c[uu][vv]=='*'&&c[xx][yy]!='H') x1=x[t], y1=y[t]; }else if(c[x[t]][y[t]]=='H') x1=x[t], y1=y[t]; if(c[uu][vv]=='*') u1=u[t], v1=v[t]; else if(uu==x[t]&&vv==y[t]){ if(c[xx][yy]=='*'&&c[uu][vv]!='H') u1=u[t], v1=v[t]; }else if(c[u[t]][v[t]]=='H'){ if(u[t]!=x[t] || v[t]!=y[t]) u1=u[t], v1=v[t]; }*/ if(c[xx][yy] == '*' ) x1=x[t], y1=y[t];// ‘*'不能去 else if(c[x[t]][y[t]]=='H') x1=x[t], y1=y[t];//已经在’H'上,不能移动 if(c[uu][vv]=='*') u1=u[t], v1=v[t]; else if(c[u[t]][v[t]]=='H'){ if(u[t]!=x[t] || v[t]!=y[t]) u1=u[t], v1=v[t];//若两球在同一个‘H’上,则只移动第二个 } if(x1==u1 && y1==v1 && c[x1][y1]!='H')continue;//两球重合 if(f[x1][y1][u1][v1]>f[x[t]][y[t]][u[t]][v[t]]+1){ if(c[x1][y1]=='H'&&c[u1][v1]=='H'&&(x1!=u1||y1!=v1)) {//找到解 ans=f[x[t]][y[t]][u[t]][v[t]]+1; return; } f[x1][y1][u1][v1]=f[x[t]][y[t]][u[t]][v[t]]+1; f[u1][v1][x1][y1]=f[x[t]][y[t]][u[t]][v[t]]+1; x[p]=x1; y[p]=y1; u[p]=u1; v[p]=v1; p++; } } } } int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif int T; cin>>T; while(T--){ readdata(); bfs(); if(ans==-1) cout<<"Sorry , sir , my poor program fails to get an answer."<<endl; else cout<<ans<<endl; } return 0; }