noip2013 华容道

 

题目描述

 

【问题描述】

 

小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间。

 

小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的:

 

  1. 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的;

  2. 有些棋子是固定的,有些棋子则是可以移动的;

  3. 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白格子上。

 

游戏的目的是把某个指定位置可以活动的棋子移动到目标位置。

 

给定一个棋盘,游戏可以玩 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。

 

 

 

输入输出样例

 

输入样例#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
输出样例#1:
2
-1

 

说明

 

【输入输出样例说明】

 

棋盘上划叉的格子是固定的,红色格子是目标位置,圆圈表示棋子,其中绿色圆圈表示目标棋子。

 

  1. 第一次游戏,空白格子的初始位置是 (3, 2)(图中空白所示),游戏的目标是将初始位置在(1, 2)上的棋子(图中绿色圆圈所代表的棋子)移动到目标位置(2, 2)(图中红色的格子)上。

 

移动过程如下:

 

 

  1. 第二次游戏,空白格子的初始位置是(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 }
code

 

posted @ 2017-08-21 12:11  A_LEAF  阅读(231)  评论(0编辑  收藏  举报