[Bzoj1003][ZJOI2006]物流运输(spfa+dp)

题目链接: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 }

 

转载于:https://www.cnblogs.com/sainsist/p/11116517.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值