题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1003
比较简单的dp,dp[i]为1-i天最小费用,dp方程为dp[i] = min(dp[i], dp[j] + c[j + 1][i] * (i - j) + k),(0<=j<i),c[i][j]为第i天到第j天都能走的最短路。
因为数据贼小,所有求最短路的方法都可以预处理出来c数组。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int INF = 1e9 + 7; 5 struct node { 6 int e, w, next; 7 }edge[11000]; 8 int head[25], len; 9 ll dp[110]; 10 int st[25][110]; 11 ll c[110][110]; 12 int dis[25]; 13 int vis[25], vis2[25]; 14 void init() { 15 memset(head, -1, sizeof(head)); 16 len = 0; 17 memset(dp, 0x7f, sizeof(dp)); 18 } 19 void add(int s, int e, int w) { 20 edge[len].e = e; 21 edge[len].w = w; 22 edge[len].next = head[s]; 23 head[s] = len++; 24 } 25 int spfa(int n) { 26 queue<int>q; 27 for (int i = 1; i <= n; i++) 28 dis[i] = INF, vis2[i] = 0; 29 dis[1] = 0; 30 vis2[1] = 1; 31 q.push(1); 32 while (!q.empty()) { 33 int x = q.front(); 34 q.pop(); 35 vis2[x] = 0; 36 for (int i = head[x]; i != -1; i = edge[i].next) { 37 int y = edge[i].e; 38 if (vis[y])continue; 39 if (dis[y] > dis[x] + edge[i].w) { 40 dis[y] = dis[x] + edge[i].w; 41 if (!vis2[y]) { 42 q.push(y); 43 vis2[y] = 1; 44 } 45 } 46 } 47 } 48 return dis[n]; 49 } 50 int main() { 51 int n, m, k, s, x, y, z; 52 scanf("%d%d%d%d", &n, &m, &k, &s); 53 init(); 54 for (int i = 1; i <= s; i++) { 55 scanf("%d%d%d", &x, &y, &z); 56 add(x, y, z); 57 add(y, x, z); 58 } 59 scanf("%d", &s); 60 for (int i = 1; i <= s; i++) { 61 scanf("%d%d%d", &x, &y, &z); 62 for (int j = y; j <= z; j++) 63 st[x][j] = 1; 64 } 65 for (int i = 1; i <= n; i++) { 66 for (int j = 1; j <= n; j++) { 67 memset(vis, 0, sizeof(vis)); 68 for (int q = i; q <= j; q++) 69 for (int w = 1; w <= m; w++) 70 if (st[w][q])vis[w] = 1; 71 c[i][j] = spfa(m); 72 } 73 } 74 for (int i = 1; i <= n; i++) { 75 dp[i] = (ll)c[1][i] * i; 76 for (int j = 0; j < i; j++) 77 dp[i] = min(dp[i], dp[j] + c[j + 1][i] * (i - j) + k); 78 } 79 printf("%lld\n", dp[n]); 80 return 0; 81 }