noip2013 华容道
题目描述
【问题描述】
小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间。
小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:
-
在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;
-
有些棋子是固定的,有些棋子则是可以移动的;
- 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。
游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。
给定一个棋盘,游戏可以玩 q 次,当然,每次棋盘上固定的格子是不会变的, 但是棋盘上空白的格子的初始位置、 指定的可移动的棋子的初始位置和目标位置却可能不同。第 i 次
玩的时候, 空白的格子在第 EXi 行第 EYi 列,指定的可移动棋子的初始位置为第 SXi 行第 SYi列,目标位置为第 TXi 行第 TYi 列。
假设小 B 每秒钟能进行一次移动棋子的操作,而其他操作的时间都可以忽略不计。请你告诉小 B 每一次游戏所需要的最少时间,或者告诉他不可能完成游戏。
输入输出格式
输入格式:
输入文件为 puzzle.in。
第一行有 3 个整数,每两个整数之间用一个空格隔开,依次表示 n、m 和 q;
接下来的 n 行描述一个 n*m 的棋盘,每行有 m 个整数,每两个整数之间用一个空格隔开,每个整数描述棋盘上一个格子的状态,0 表示该格子上的棋子是固定的,1 表示该格子上的棋子可以移动或者该格子是空白的。接下来的 q 行,每行包含 6 个整数依次是 EXi、EYi、SXi、SYi、TXi、TYi,每两个整数之间用一个空格隔开,表示每次游戏空白格子的位置,指定棋子的初始位置和目标位置。
输出格式:
输出文件名为 puzzle.out。
输出有 q 行,每行包含 1 个整数,表示每次游戏所需要的最少时间,如果某次游戏无法完成目标则输出−1。
输入输出样例
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
2
-1
说明
【输入输出样例说明】
棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。
- 第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。
移动过程如下:
- 第二次游戏,空白格子的初始位置是(1, 2)(图中空白所示),游戏的目标是将初始位置在(2, 2)上的棋子(图中绿色圆圈所示)移动到目标位置 (3, 2)上。
要将指定块移入目标位置,必须先将空白块移入目标位置,空白块要移动到目标位置,必然是从位置(2, 2)上与当前图中目标位置上的棋子交换位置,之后能与空白块交换位置的只有当前图中目标位置上的那个棋子,因此目标棋子永远无法走到它的目标位置, 游戏无
法完成。
【数据范围】
对于 30%的数据,1 ≤ n, m ≤ 10,q = 1;
对于 60%的数据,1 ≤ n, m ≤ 30,q ≤ 10;
对于 100%的数据,1 ≤ n, m ≤ 30,q ≤ 500。
solution
暴力(70):
定义f[x1][y1][x2][y2]为空格在(x1,y1),目标棋子在(x2,y2),时的最小步数
之后bfs就行
正解:
也是bfs
预处理出来数组 g[x][y][k][kk] 1<=k,kk<=4
意义是 当前棋子在(x,y)白棋子在k方向(上下左右),想要走到kk方向的最小步数
之后对于每次询问
首先把白格子挪到目标旗子周围,之后把目标棋子挪到目标位置,bfs利用g[][][][]数组
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int DUI=20000006; 8 const int INF=0x7fffffff; 9 10 inline int minn(int a,int b){return a<b?a:b;} 11 12 struct Queue 13 { 14 int x,y; 15 }; 16 17 queue<Queue> q; 18 int n,m,Q,qqq; 19 int bx[6]={0,-1,1,0,0,0}; 20 int by[6]={0,0,0,-1,1,0};// 1 上 2 下 3 左 4 右 21 int f[36][36][6],ha[6],flag[36][36],vis[36][36][6]; 22 int a[36][36],g[36][36][6][6],d[36][36]; 23 int whx,why,sx,sy,tx,ty; 24 25 void out11(); 26 27 void chu() 28 { 29 mem(g,60); 30 qqq=g[0][0][0][0]; 31 Queue now; 32 int x,y; 33 for(int i=1;i<=n;++i) 34 for(int j=1;j<=m;++j) 35 { 36 if(a[i][j]==0) 37 continue; 38 for(int bai=1;bai<=4;++bai) 39 {//printf("saafsffas\n"); 40 if( (i+bx[bai]<1) || (i+bx[bai]>n) || (j+by[bai]<1) || (j+by[bai]>m) || (a[i+bx[bai]][j+by[bai]]==0) ) 41 continue; 42 for(int tt=1;tt<=4;++tt) 43 { 44 if( (i+bx[tt]<1) || (i+bx[tt]>n) || (j+by[tt]<1) || (j+by[tt]>m) || (a[i+bx[tt]][j+by[tt]]==0) ) 45 continue; 46 //printf("i=%d j=%d\n",i,j); 47 if(bai==tt) 48 { 49 g[i][j][bai][tt]=0; 50 continue; 51 } 52 53 54 55 while(!q.empty())q.pop(); 56 mem(d,60);mem(flag,0); 57 sx=i+bx[bai];sy=j+by[bai]; 58 tx=i+bx[tt];ty=j+by[tt]; 59 d[sx][sy]=0;flag[sx][sy]=1; 60 q.push((Queue){sx,sy}); 61 while(!q.empty()) 62 { 63 64 now=q.front();q.pop(); 65 x=now.x;y=now.y;flag[x][y]=0; 66 //if(x==tx&&y==ty) 67 // break; 68 69 for(int k=1;k<=4;++k) 70 { 71 if(x+bx[k]<1||x+bx[k]>n||y+by[k]<1||y+by[k]>m||a[x+bx[k]][y+by[k]]==0|| (x+bx[k]==i&&y+by[k]==j) ) 72 continue; 73 //printf("sdasdasd\n"); 74 if(d[x+bx[k]][y+by[k]]>d[x][y]+1) 75 { 76 d[x+bx[k]][y+by[k]]=d[x][y]+1; 77 if(!flag[x+bx[k]][y+by[k]]) 78 { 79 q.push((Queue){x+bx[k],y+by[k]}); 80 flag[x+bx[k]][y+by[k]]=1; 81 } 82 } 83 } 84 } 85 86 //g[i][j][bai][tt]=d[tx][ty]+1; 87 g[i][j][bai][tt]=d[tx][ty]; 88 89 //out11(); 90 91 //printf("i=%d j=%d k=%d l=%d g[][][][]=%d\n",i,j,bai,tt,g[i][j][bai][tt]); 92 } 93 } 94 } 95 }// yes 96 97 int bfs1() 98 { 99 Queue now; 100 int x,y; 101 mem(d,60); 102 while(!q.empty())q.pop(); 103 mem(flag,0); 104 d[whx][why]=0;flag[whx][why]=1; 105 q.push((Queue){whx,why}); 106 while(!q.empty()) 107 { 108 now=q.front();q.pop(); 109 x=now.x;y=now.y;flag[x][y]=0; 110 for(int k=1;k<=4;++k) 111 { 112 if(x+bx[k]<1||x+bx[k]>n||y+by[k]<1||y+by[k]>m||a[x+bx[k]][y+by[k]]==0|| (x+bx[k]==sx&&y+by[k]==sy) ) 113 continue; 114 if(d[x+bx[k]][y+by[k]]>d[x][y]+1) 115 { 116 d[x+bx[k]][y+by[k]]=d[x][y]+1; 117 if(!flag[x+bx[k]][y+by[k]]) 118 { 119 q.push((Queue){x+bx[k],y+by[k]}); 120 flag[x+bx[k]][y+by[k]]=1; 121 } 122 } 123 } 124 } 125 126 for(int i=1;i<=4;++i) 127 if(d[sx+bx[i]][sy+by[i]]<qqq) 128 return 1; 129 return 0; 130 } 131 132 struct son 133 { 134 int x,y,k; 135 }; 136 queue<son> dui; 137 138 int bfs2() 139 { 140 son now; 141 int x,y,nowk; 142 mem(f,60);mem(vis,0); 143 for(int i=1;i<=4;++i) 144 { 145 if(sx+bx[i]<1||sx+bx[i]>n||sy+by[i]<1||sy+by[i]>m||a[sx+bx[i]][sy+by[i]]==0||d[sx+bx[i]][sy+by[i]]==qqq) 146 continue; 147 f[sx][sy][i]=d[sx+bx[i]][sy+by[i]]; 148 vis[sx][sy][i]=1; 149 //printf("ssdad=%d\n",d[sx+bx[i]][sy+by[i]]); 150 dui.push((son){sx,sy,i}); 151 } 152 153 //out11(); 154 155 while(!dui.empty()) 156 { 157 now=dui.front();dui.pop(); 158 x=now.x;y=now.y;nowk=now.k; 159 vis[x][y][nowk]=0; 160 161 for(int i=1;i<=4;++i) 162 { 163 if(x+bx[i]<1|| (x+bx[i]>n) || (y+by[i]<1) || (y+by[i]>m) || (a[x+bx[i]][y+by[i]]==0) ) 164 continue; 165 //printf("hhahahahahha\n"); 166 int temp1=f[x+bx[i]][y+by[i]][ha[i]]; 167 int temp2=f[x][y][nowk]+1+g[x][y][nowk][i]; 168 //printf("%d %d\n",temp1,temp2); 169 if(temp1>temp2) 170 { 171 172 f[x+bx[i]][y+by[i]][ha[i]]=f[x][y][nowk]+1+g[x][y][nowk][i]; 173 if(!vis[x+bx[i]][y+by[i]][ha[i]])//////???????? 174 { 175 dui.push((son){x+bx[i],y+by[i],ha[i]}); 176 vis[x+bx[i]][y+by[i]][ha[i]]=1; 177 } 178 } 179 } 180 } 181 182 //out11(); 183 184 int ans=INF; 185 for(int i=1;i<=4;++i) 186 ans=minn(ans,f[tx][ty][i]); 187 return ans; 188 } 189 190 void out11() 191 { 192 printf("\n"); 193 for(int k=1;k<=4;++k) 194 { 195 for(int i=1;i<=n;++i) 196 { 197 for(int j=1;j<=m;++j) 198 printf("%d ",f[i][j][k]); 199 printf("\n"); 200 } 201 printf("\n"); 202 } 203 204 /*for(int i=1;i<=n;++i) 205 { 206 for(int j=1;j<=m;++j) 207 printf("%d ",d[i][j]); 208 printf("\n"); 209 }*/ 210 /*for(int i=1;i<=n;++i) 211 for(int j=1;j<=m;++j) 212 for(int k=1;k<=4;++k) 213 for(int l=1;l<=4;++l) 214 if(g[i][j][k][l]!=qqq) 215 printf("i=%d j=%d k=%d l=%d g[][][][]=%d\n",i,j,k,l,g[i][j][k][l]);*/ 216 printf("\n"); 217 } 218 219 int main(){ 220 221 //freopen("1.txt","r",stdin); 222 223 scanf("%d%d%d",&n,&m,&Q); 224 for(int i=1;i<=n;++i) 225 for(int j=1;j<=m;++j) 226 scanf("%d",&a[i][j]); 227 chu(); 228 ha[1]=2;ha[2]=1;ha[3]=4;ha[4]=3; 229 230 //out11(); 231 232 while(Q--) 233 { 234 scanf("%d%d%d%d%d%d",&whx,&why,&sx,&sy,&tx,&ty); 235 if(sx==tx&&sy==ty) 236 { 237 printf("0\n"); 238 continue; 239 } 240 if(bfs1()==0) 241 { 242 printf("-1\n"); 243 continue; 244 } 245 int temp=bfs2(); 246 if(temp>=qqq) 247 { 248 printf("-1\n"); 249 continue; 250 } 251 printf("%d\n",temp); 252 } 253 254 //while(1); 255 return 0; 256 }