版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83513294
题意:存在有m个码头,修改运输成本k,以及e条路,让设计一条n天的路线,使得花费最小,每一条路线都是从头跑到尾。
题解:我们可以先到设计
表示从第一天到第
天的最小花费,
表示第
天到第
天从1->n的最短路是多少,通过dijkstra或者spfa都能跑出来,需要标记在
天内哪些码头能用,然后通过dp来转移,转移方程如下:
表示转了路线一次,剩下的
天走
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define g getchar()
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
inline int read() {
int res = 0, f = 1; char ch = g;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = g;}
while(ch >= '0' && ch <= '9') {res = res * 10 + ch - '0'; ch = g;}
return res;
}
struct Edge {
int to, next, val;
} e[maxn];
int h[maxn], d, n, k, m, cnt;
ll f[200], t[200][200];
int flag[200][200];
void add(int u, int v, int w) {
e[cnt].to = v;
e[cnt].val = w;
e[cnt].next = h[u];
h[u] = cnt++;
}
int spfa(int l, int r) {
int lim[maxn], vis[maxn], dis[maxn];
met(lim, 0);
met(vis, 0);
for(int i = 1; i <= n; i++) dis[i] = inf;
rep(i, 1, n) rep(j, l, r) if(flag[i][j]) lim[i] = 1;
queue<int> q;
q.push(1);
dis[1] = 0;
vis[1] = 1;
while(!q.empty()) {
int u = q.front();
q.pop();
for(register int i = h[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(!lim[v] && dis[v] > dis[u] + e[i].val) {
dis[v] = dis[u] + e[i].val;
if(!vis[v]) {
vis[v] = 1;
q.push(v);
}
}
}
vis[u] = 0;
}
return dis[n];
}
int main() {
met(h, -1);
cnt = 0;
d = read(); n = read(); k = read(); m = read();
int u, v, w;
rep(i, 1, m) {
u = read(), v = read(), w = read();
add(u, v, w); add(v, u, w);
}
int x = read();
int l, r, p;
while(x--) {
p = read(), l = read(), r = read();
for(register int i = l; i <= r; i++) flag[p][i] = 1;
}
rep(i, 1, d) rep(j, 1, d) t[i][j] = spfa(i, j);
rep(i, 1, d) {
f[i] = (ll)t[1][i] * (ll)i;
rep(j, 0, i) {
f[i] = min(f[i], k + f[j] + t[j + 1][i] * (i - j));
}
}
printf("%lld\n", f[d]);
return 0;
}