[noip2013]华容道
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1 个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
2. 有些棋子是固定的,有些棋子则是可以移动的;
3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。
游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第 EX[i] 行第 EY[i] 列,指定的可移动棋子的初始位置为第 SX[i] 行第 SY[i] 列,目标位置为第 TX[i] 行第 TY[i] 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请
你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
题解:
bfs,O(n^4)是比较容易看出来的60分做法(考试推荐),单组数据可过,由于多组数据q到达了500,所以40%会T;
那么从bfs的思路入手,可以发现bfs实际上在每次指定的格子移动一步时,都有大量的无用状态,而同时,图中的每个点在空格位置确定时,想移动一步的步数是一定的,那么可以考虑一个n^4的预处理,把每次这个格子要转移时花费的步数记录下来,就可以实现优化;
实现比较繁琐,见代码;
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iomanip> #include<map> #include<set> #include<vector> #include<ctime> #include<cmath> #define LL long long using namespace std; #define LL long long #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++) #define max(x,y) ((x)<(y)?(y):(x)) #define min(x,y) ((x)<(y)?(x):(y)) #define FILE "Puzzle" const int maxn=50,inf=100000000; int read(){ int x=0;bool flag=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')flag=1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return flag?-x:x; } struct N{ int y,next,v; }e[500000]; int linkk[200000],len=0; void insert(int x,int y,int v){ e[++len].y=y; e[len].next=linkk[x]; linkk[x]=len; e[len].v=v; } int n,m,Q; int a[maxn][maxn]; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; int f[maxn][maxn][4][4]; int d[maxn][maxn]; int V,A[maxn][maxn][4]; struct node{ int bx,by; }q[2000000]; int head=0,tail=0; int bfs(int sx,int sy,int ex,int ey){ memset(d,10,sizeof(d)); head=0,tail=0;int x,y,xx,yy; q[++tail].bx=sx,q[tail].by=sy; d[sx][sy]=0; while(++head<=tail){ x=q[head].bx,y=q[head].by;//空白所在点 if(x==ex&&y==ey)return d[x][y]; up(i,0,3){ xx=x+dx[i],yy=y+dy[i]; if(!a[xx][yy])continue; if(d[xx][yy]>=d[x][y]+1){ d[xx][yy]=d[x][y]+1; q[++tail].bx=xx,q[tail].by=yy; } } } return d[ex][ey]; } void init(){ n=read(),m=read(),Q=read(); up(i,1,n)up(j,1,m){ a[i][j]=read(); up(k,0,3)A[i][j][k]=++V; } int sx,sy,ex,ey; up(i,1,n)up(j,1,m){ if(!a[i][j])continue; up(w,0,3){ sx=i+dx[w],sy=j+dy[w]; if(!a[sx][sy])continue; insert(A[i][j][w],A[sx][sy][w^1],1); up(z,0,3){ if(w==z)continue; ex=i+dx[z],ey=j+dy[z]; if(!a[ex][ey])continue; a[i][j]=0; int move=bfs(sx,sy,ex,ey)+1; if((move<=inf))insert(A[i][j][w],A[ex][ey][z^1],move); a[i][j]=1; } } } } int inx,qu[200000]; int dist[200000]; bool vis[200000]; int spfa(int S,int T){ head=tail=0;qu[++tail]=S; memset(dist,10,sizeof(dist)); memset(vis,0,sizeof(vis)); dist[S]=0;int x; while(++head<=tail){ x=qu[head]; vis[x]=0; for(int i=linkk[x];i;i=e[i].next){ if(dist[e[i].y]>=dist[x]+e[i].v){ dist[e[i].y]=dist[x]+e[i].v; if(!vis[e[i].y]){ qu[++tail]=e[i].y; vis[e[i].y]=1; } } } } return dist[T]>=inf?-1:dist[T]; } void work(){ int bx,by,sx,sy,tx,ty,x,y,xx,yy; while(Q--){ bx=read(),by=read(),sx=read(),sy=read(),tx=read(),ty=read(); if(sx==tx&&sy==ty){printf("0\n");continue;} if(!a[sx][sy]||!a[tx][ty]){printf("-1\n");continue;} int S=++V,T=++V; a[sx][sy]=0; up(k,0,3){ x=sx+dx[k],y=sy+dy[k]; if(!a[x][y])continue; int dis=bfs(bx,by,x,y); if(dis<inf)insert(S,A[sx][sy][k],dis); } a[sx][sy]=1; up(k,0,3){ x=tx+dx[k],y=ty+dy[k]; if(!a[x][y])continue; insert(A[tx][ty][k],T,0); } printf("%d\n",spfa(S,T)); } } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); init(); work(); return 0; }