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

时间:2022-03-19 05:30:06

题目链接: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数组。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e9 + ;
struct node {
int e, w, next;
}edge[];
int head[], len;
ll dp[];
int st[][];
ll c[][];
int dis[];
int vis[], vis2[];
void init() {
memset(head, -, sizeof(head));
len = ;
memset(dp, 0x7f, sizeof(dp));
}
void add(int s, int e, int w) {
edge[len].e = e;
edge[len].w = w;
edge[len].next = head[s];
head[s] = len++;
}
int spfa(int n) {
queue<int>q;
for (int i = ; i <= n; i++)
dis[i] = INF, vis2[i] = ;
dis[] = ;
vis2[] = ;
q.push();
while (!q.empty()) {
int x = q.front();
q.pop();
vis2[x] = ;
for (int i = head[x]; i != -; i = edge[i].next) {
int y = edge[i].e;
if (vis[y])continue;
if (dis[y] > dis[x] + edge[i].w) {
dis[y] = dis[x] + edge[i].w;
if (!vis2[y]) {
q.push(y);
vis2[y] = ;
}
}
}
}
return dis[n];
}
int main() {
int n, m, k, s, x, y, z;
scanf("%d%d%d%d", &n, &m, &k, &s);
init();
for (int i = ; i <= s; i++) {
scanf("%d%d%d", &x, &y, &z);
add(x, y, z);
add(y, x, z);
}
scanf("%d", &s);
for (int i = ; i <= s; i++) {
scanf("%d%d%d", &x, &y, &z);
for (int j = y; j <= z; j++)
st[x][j] = ;
}
for (int i = ; i <= n; i++) {
for (int j = ; j <= n; j++) {
memset(vis, , sizeof(vis));
for (int q = i; q <= j; q++)
for (int w = ; w <= m; w++)
if (st[w][q])vis[w] = ;
c[i][j] = spfa(m);
}
}
for (int i = ; i <= n; i++) {
dp[i] = (ll)c[][i] * i;
for (int j = ; j < i; j++)
dp[i] = min(dp[i], dp[j] + c[j + ][i] * (i - j) + k);
}
printf("%lld\n", dp[n]);
return ;
}