有 n n n个点,每个点之间的边权是一个周期。
求从 1 1 1出发经过 m m m条边到 n n n的最小权值
S o l u t i o n 1 Solution\ 1 Solution 1
d p dp dp
设 f i , j f_{i,j} fi,j表示第 i i i天到达第 j j j个点的最少花费
则得出转移方程: f i , j = m i n ( f i , j , f i − 1 , k + a k , j , ( a i , j , 0 − 1 ) m o d k + 1 ) f_{i,j} = min(f_{i,j},\ f_{i-1,k}+a_{k,j,(a_{i,j,0}-1)\ mod\ k + 1)} fi,j=min(fi,j, fi−1,k+ak,j,(ai,j,0−1) mod k+1)
a i , j , 0 a_{i,j,0} ai,j,0表示周期长度
a i , j , k a_{i,j,k} ai,j,k表示从点 i i i到点 j j j在周期中第 k k k天的花费,若 a i , j , k = 0 a_{i,j,k} =0 ai,j,k=0,则周期中的第 k k k天不能走
S o l u t i o n 2 Solution\ 2 Solution 2
分层图SPFA
这里不再赘述
#include
#include
#include
#define rr register
using namespace std;
const int inf = 1e9;
int n, m;
int a[101][101][21], f[201][101];
inline signed read() {
int f = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) f = f * 10 + c - 48, c = getchar();
return f;
}
void write(int x) {
if (x > 9) write(x/10); putchar(x%10+48); return;
}
signed main() {
/*freopen("lines.in", "r", stdin);
freopen("lines.out", "w", stdout);*/
n = read(); m = read();
for (rr int i = 1; i <= n; ++i) {
for (rr int j = 1; j <= n; ++j)
if (i != j) {
a[i][j][0] = read();
for (rr int T = 1; T <= a[i][j][0]; ++T)
a[i][j][T] = read(),
a[i][j][T] = a[i][j][T] == 0 ? inf : a[i][j][T];
}
}
for (rr int i = 0; i <= m; ++i)
for (rr int j = 0; j <= n; ++j)
f[i][j] = inf;
f[0][1] = 0;
for (rr int k = 1; k <= m; ++k)
for (rr int i = 1; i <= n; ++i)
for (rr int j = 1; j <= n; ++j)
if (i != j)
f[k][j] = min(f[k][j], f[k-1][i] + a[i][j][(k-1)%a[i][j][0]+1]);
write(f[m][n] == inf ? 0 : f[m][n]);
return 0;
}