Description
这是一个传说中的勇者凡喵,救出被掳走的公主,顺道打倒妄图控制世界的恶龙拯救世界的故事。
有趣的是,凡喵这一次进入恶龙巢穴时,发现恶龙刚好外出。于是凡喵决定先去拯救公主,至于拯救世界什么 的,还是开心最重要。
凡喵出发前从冒险者公会购买了一张恶龙巢穴的地图。
恶龙巢穴建立在地下。一共有 H 层,从地下 1 层到地下 H 层。每层是一个迷宫,有 N × M 个格子。
用 (x, y, i) 表示第 i 层第 x 行第 y 列的格子,凡喵已经知道入口的位置是 (SX, SY, 1) 而公主被囚禁在 (T X, T Y, H)。
格子有 3 种类型,分别是陷阱,传送门和空地。凡喵每 1 分钟可以从一个格子走到相邻的格子(相邻的定义 是在同一层且有一条公共边)。当然,凡喵是不能走到陷阱上的。
传送门一共有 10 种,第 i 层的传送门可以将凡喵传送到第 i + 1 层任意一个同类型的传送门处。传送是不需 要时间的。当传送到一个传送门时,可以立刻再从这个传送门出发传送到下一层。
现在凡喵想要知道,自己最少要多少分钟才能见到公主。
Data Constraint
Solution
我们可以每次将有颜色的点加入spfa的起始队列,跑完spfa后我们选出每种颜色在该层的与起点最近距离,作为答案更新下一层的同种颜色的起始距离。
Code
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=
2e2+
5;
const int f[
4][
2]={{
0,
1},{
1,
0},{
0,-
1},{-
1,
0}};
struct code{
int x,y;
}v[maxn*maxn*
10];
int a[
11][maxn][maxn],d[
11][maxn][maxn],b[
20],bz[maxn][maxn];
int sx,sy,tx,ty,n,m,h,i,t,j,k,l,x,y,z,p,num;
void spfa(
int s){
int i=
0,j=num,x,k,t;
while (i<j){
++i;z=d[s][v[i].x][v[i].y];
for (k=
0;k<
4;k++){
x=v[i].x+f[k][
0];y=v[i].y+f[k][
1];
if (x>n || x<
1 || y>m || y<
1 || d[s][x][y]<=z+
1 || a[s][x][y]<
0)
continue;
d[s][x][y]=z+
1;
if (!bz[x][y]) v[++j].x=x,v[j].y=y,bz[x][y]=
1;
}
bz[v[i].x][v[i].y]=
0;
}
}
int main(){
freopen(
"rpg.in",
"r",stdin);freopen(
"rpg.out",
"w",stdout);
scanf(
"%d%d%d",&n,&m,&h);
for (i=
1;i<=h;i++)
for (j=
1;j<=n;j++)
for (k=
1;k<=m;k++)
scanf(
"%d",&a[i][j][k]);
scanf(
"%d%d%d%d",&sx,&sy,&tx,&ty);
if (a[
1][sx][sy]<
0 || a[h][tx][ty]<
0){
printf(
"-1\n");
return 0;
}
memset(d,
127,
sizeof(d));p=d[
1][
1][
1];
d[
1][sx][sy]=
0;
for (i=
1;i<=h;i++){
num=
0;
for (j=
1;j<=n;j++)
for (k=
1;k<=m;k++)
if (d[i][j][k]!=p)v[++num].x=j,v[num].y=k,bz[j][k]=
1;
spfa(i);
memset(b,
127,
sizeof(b));
for (j=
1;j<=n;j++)
for (k=
1;k<=m;k++)
b[a[i][j][k]]=min(b[a[i][j][k]],d[i][j][k]);
for (j=
1;j<=n;j++)
for (k=
1;k<=m;k++)
if (a[i+
1][j][k]>
0) d[i+
1][j][k]=b[a[i+
1][j][k]];
}
if (d[h][tx][ty]!=p)
printf(
"%d\n",d[h][tx][ty]);
else printf(
"-1\n");
}