LG1772 [ZJOI2006] 物流运输 dp+最短路

题意简述

传送门


问题分析

这一题乍一看没有什么头绪。

考虑设 f(i) 代表到第 i 天结束,所花费的最小费用。

CS,T 代表从第 S 天到第 T 天走同一条最短路的花费,暴力标记掉 [S,T] 范围内任意一天不可走的点。

所有的 CS,T 是可以通过跑 n2 次最短路求出来的。

这样显然有 f(i)=minj=1i1f(j)+Cj+1,i×(ij)+k

预处理要把 f(i) 赋值为 C1,i×i

时间复杂度应该是 O(n3dlogn)


代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
template < typename Tp >
void read(Tp &x) {
x = 0; int fh = 1; char ch = 1;
while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if(ch == '-') fh = -1, ch = getchar();
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
x *= fh;
}
const int maxe = 2000 + 7;
const int maxn = 100 + 7;
int n, m, k, e, d;
int Head[maxn], to[maxe], Next[maxe], tot, w[maxe];
void add(int x, int y, int z) {
to[++tot] = y, Next[tot] = Head[x], Head[x] = tot, w[tot] = z;
}
int Cos[maxn][maxn];
int dis[maxn];
bool inq[maxn];
priority_queue <pair <int, int> > Q;
bool ok[maxn];
void dijkstra(void) {
memset(dis, 0x3f, sizeof(dis));
dis[1] = 0; Q.push(make_pair(0, 1));
memset(inq, false, sizeof(inq));
while(Q.size()) {
int x = Q.top().second; Q.pop();
if(inq[x]) continue; inq[x] = true;
for(int i = Head[x]; i; i = Next[i]) {
int t = to[i]; if(ok[t]) continue;
if(dis[t] > dis[x] + w[i]) {
dis[t] = dis[x] + w[i];
Q.push(make_pair(-dis[t], t));
}
}
}
}
int p[maxn], L[maxn], R[maxn];
void Init(void) {
read(n); read(m); read(k); read(e);
for(int i = 1, x, y, z; i <= e; i++) {
read(x); read(y); read(z);
add(x, y, z); add(y, x, z);
}
read(d);
for(int i = 1; i <= d; i++) {
read(p[i]); read(L[i]); read(R[i]);
}
}
void mark(int S, int T) {
memset(ok, false, sizeof(ok));
for(int i = 1; i <= d; i++) {
if(L[i] > T || R[i] < S) continue;
ok[p[i]] = true;
}
}
LL dp[maxn];
void Work(void) {
for(int S = 1; S <= n; S++) {
for(int T = S; T <= n; T++) {
mark(S, T);
dijkstra();
Cos[S][T] = dis[m];
}
}
memset(dp, 0x3f, sizeof(dp));
for(int i = 1; i <= n; i++) {
if(Cos[1][i] != 0x3f3f3f3f) dp[i] = Cos[1][i] * i;
}
for(int i = 2; i <= n; i++) {
for(int j = 1; j < i; j++) {
if(Cos[j + 1][i] != 0x3f3f3f3f) {
dp[i] = min(dp[i], dp[j] + Cos[j + 1][i] * (i - j) + k);
}
}
}
printf("%lld\n", dp[n]);
}
int main(void) {
Init();
Work();
return 0;
}
posted @   览遍千秋  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示