【noip 2014】提高组Day2T3.华容道
Description
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
1.在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
2.有些棋子是固定的,有些棋子则是可以移动的;
3.任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。 游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的,但是棋盘上空白的格子的初始位置、指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次玩的时候,空白的格子在第EXi行EYi列,指定的可移动棋子的初始位置为第SXi行第SYi 列,目标位置为第TXi 行第TYi列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
Input
第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。
接下来的 q 行,每行包含 6 个整数依次是EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。
Output
输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出−1。
Sample Input
3 4 2
0 1 1 1
0 1 1 0
0 1 0 0
3 2 1 2 2 2
1 2 2 2 3 2
Sample Output
2
-1
讲道理,这题的预处理真的不是来恶心人的吗TAT
然后有一个小技巧:用1代表上,2代表左,3代表右,4代表下,则a的反方向就是5-a。
存一存代码。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int inf=0x3f3f3f3f; 7 int n,m,k,ex,ey,sx,sy,tx,ty,ans; 8 int map[35][35],deep[35][35],dis[35][35][5],mov[35][35][5][5]; 9 bool d[35][35],in[35][35][5]; 10 struct node{int x,y,k;}t1,t2; 11 int read() 12 { 13 int x=0,f=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 15 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 16 return x*f; 17 } 18 node move(node t,int k) 19 { 20 if(k==1)t.x--;if(k==2)t.y--; 21 if(k==3)t.y++;if(k==4)t.x++; 22 return t; 23 } 24 int bfs(node s,node t) 25 { 26 node now,to; 27 memset(deep,0x3f,sizeof(deep)); 28 memset(d,0,sizeof(d)); 29 queue<node>q;q.push(s); 30 deep[s.x][s.y]=0;d[s.x][s.y]=true; 31 while(!q.empty()&&!d[t.x][t.y]) 32 { 33 now=q.front();q.pop(); 34 for(int k=1;k<=4;k++) 35 { 36 to=move(now,k); 37 if(!d[to.x][to.y]&&map[to.x][to.y]==1) 38 { 39 d[to.x][to.y]=true;q.push(to); 40 deep[to.x][to.y]=deep[now.x][now.y]+1; 41 } 42 } 43 } 44 return deep[t.x][t.y]; 45 } 46 void init() 47 { 48 memset(mov,0x3f,sizeof(mov)); 49 for(int i=1;i<=n;i++) 50 for(int j=1;j<=m;j++) 51 { 52 if(map[i][j]==0)continue; 53 map[i][j]=0; 54 for(int k=1;k<=4;k++) 55 for(int l=1;l<=4;l++) 56 { 57 if(l<k){mov[i][j][k][l]=mov[i][j][l][k];continue;} 58 t1=move((node){i,j,k},k);t2=move((node){i,j,l},l); 59 if(map[t1.x][t1.y]==0||map[t2.x][t2.y]==0)continue; 60 mov[i][j][k][l]=bfs(t1,t2)+1; 61 } 62 map[i][j]=1; 63 } 64 } 65 void spfa(node s,node t) 66 { 67 ans=inf; 68 if(s.x==t.x&&s.y==t.y){ans=0;return;} 69 if(map[s.x][s.y]==0||map[t.x][t.y]==0)return; 70 node now,to; 71 memset(dis,0x3f,sizeof(dis)); 72 memset(in,0,sizeof(in)); 73 queue<node>q; 74 map[s.x][s.y]=0; 75 for(int i=1;i<=4;i++) 76 { 77 q.push((node){s.x,s.y,i}); 78 in[s.x][s.y][i]=true; 79 dis[s.x][s.y][i]=bfs((node){ex,ey,0},move(s,i)); 80 } 81 map[s.x][s.y]=1; 82 while(!q.empty()) 83 { 84 now=q.front();q.pop(); 85 in[now.x][now.y][now.k]=false; 86 for(int i=1;i<=4;i++) 87 { 88 to=move(now,i);to.k=5-i; 89 if(dis[now.x][now.y][now.k]+mov[now.x][now.y][now.k][i]<dis[to.x][to.y][5-i]) 90 { 91 dis[to.x][to.y][5-i]=dis[now.x][now.y][now.k]+mov[now.x][now.y][now.k][i]; 92 if(!in[to.x][to.y][to.k])q.push(to),in[to.x][to.y][to.k]=true; 93 } 94 } 95 } 96 for(int i=1;i<=4;i++)ans=min(ans,dis[t.x][t.y][i]); 97 } 98 int main() 99 { 100 n=read();m=read();k=read(); 101 for(int i=1;i<=n;i++) 102 for(int j=1;j<=m;j++) 103 map[i][j]=read(); 104 init(); 105 for(int i=1;i<=k;i++) 106 { 107 ex=read();ey=read();sx=read();sy=read();tx=read();ty=read(); 108 spfa((node){sx,sy,0},(node){tx,ty,0}); 109 if(ans==inf)printf("-1\n"); 110 else printf("%d\n",ans); 111 } 112 return 0; 113 }