难得不卡(SPFA)
因为可爱的贝茜会走三步停一步,所以可以将这三步并为一步来考虑,花费的时间为t * 3 + cost[x][y]
需要注意的是,贝茜可以走一步再走回来,所以她周围的点也要考虑到,这样一共是16个点
另外,当贝茜到达终点时不一定正好走三步,所以要将和终点距离为(1,2)的点也连向终点
建图结束后,跑一遍最短路就可以了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
struct zzz {
int t, nex, len;
}e[500010 << 1]; int head[100010], tot;
void add(int x, int y, int z) {
e[++tot].t = y;
e[tot].len = z;
e[tot].nex = head[x];
head[x] = tot;
}
int mapp[110][110], n, t;
inline int calc(int x, int y) {
return (x-1) * n + y;
}
inline bool judge(int x, int y) {
return x >= 1 && x <= n && y >= 1 && y <= n;
}
int fx[20] = {0, -2, -1, 1, 2, 2, 1, -1, -2, 0, 1, 0, -1, 0, 3, 0, -3};
int fy[20] = {0, 1, 2, 2, 1, -1, -2, -2, -1, 1, 0, -1, 0, 3, 0, -3, 0};
bool vis[100010]; int dis[100010];
void SPFA(int s) {
memset(dis, 127, sizeof(dis)); dis[s] = 0; vis[s] = 1;
queue <int> q; q.push(s);
while(!q.empty()) {
int k = q.front(); q.pop(); vis[k] = 0;
for(int i = head[k]; i; i = e[i].nex) {
if(dis[e[i].t] > dis[k] + e[i].len) {
dis[e[i].t] = dis[k] + e[i].len;
if(!vis[e[i].t])
vis[e[i].t] = 1, q.push(e[i].t);
}
}
}
}
int main() {
n = read(), t = read();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j) mapp[i][j] = read();
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j) {
for(int k = 1; k <= 16; ++k) {
int xx = i + fx[k], yy = j + fy[k];
if(judge(xx, yy))
add(calc(i, j), calc(xx, yy), 3 * t + mapp[xx][yy]);
}
}
add(calc(n-1, n-1), calc(n, n), t << 1);
add(calc(n-2, n), calc(n, n), t << 1);
add(calc(n, n-2), calc(n, n), t << 1);
add(calc(n-1, n), calc(n, n), t);
add(calc(n, n-1), calc(n, n), t);
SPFA(calc(1, 1));
printf("%d
", dis[calc(n, n)]);
return 0;
}