【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 }
View Code
posted @ 2017-07-29 17:16  Zsnuo  阅读(365)  评论(0编辑  收藏  举报