Luogu P1772 [ZJOI2006]物流运输
【题目算法】 动态规划 $ + $ 最短路
【题目分析】
1 设 $ f_i $ 表示到第 $ i $ 天时所需的最小费用, $ a_{i, j}$ 表示从第 $ i $ 天到第 $ j $ 天使用同一条可行的从 $ 1 $ 到 $ n $ 的最短路。则:
$ F_i = \min (f_j + a_{j+1,i} * (i - j) + k;) $
$ Ans = f_m - k; $ (因为第一次加了一个 $ k $ )
2.计算 $ a_{i,j} $ 的值。枚举 $ i $ 和 $ j $ ,标记不能用的码头,然后用 $ dijkstra $ 求从 $ 1 $ 到 $ n $ 的最短路。
【算法步骤】
1.读入数据,用 $ w_{i,j} $ 记录第 $ i $ 天第 $ j $ 个不能用的码头;
2.求 $ a_{i,j} = dijkstra(); $
3.最后用 $ dp $ 求解
- $ AC $ 代码
#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 0x7fffffff/2
#define MAXN 105
#define ll long long
ll N,M,K,E,D,a[MAXN][MAXN],g[MAXN][MAXN],w[MAXN][MAXN],dis[MAXN],f[MAXN];
bool bj[MAXN],vst[MAXN];
int dij() {
ll k,minn;
for (ll i=1;i<=M;i++) {dis[i]=INF; vst[i]=0;}
dis[1]=0;
for (ll i=1;i<=M;i++) {
k=0; minn=INF;
for (ll j=1;j<=M;j++) {
if (!vst[j]&&!bj[j]&&dis[j]<minn) {minn=dis[j]; k=j;}
}
if (!k) break;
vst[k]=1;
for (ll j=1;j<=M;j++) {
if (g[k][j]>0&&dis[k]+g[k][j]<dis[j]) dis[j]=g[k][j]+dis[k];
}
}
return dis[M];
}
void init() {
for (ll i=1;i<=N;i++) {
for (ll j=i;j<=N;j++) {
memset(bj,0,sizeof(bj));
for (ll k=i;k<=j;k++) for (ll l=1;l<=w[k][0];l++) bj[w[k][l]]=1;
a[i][j]=dij();
}
}
}
void dp() {
for (ll i=1;i<=N;i++) {
f[i]=INF;
for (ll j=0;j<i;j++) f[i]=min(f[j]+a[j+1][i]*(i-j)+K,f[i]);
}
printf("%lld",f[N]-K);
}
void read() {
ll x,y,z,p,daya,dayb;
scanf("%lld %lld %lld %lld",&N,&M,&K,&E);
for (ll i=1;i<=E;i++) {scanf("%lld %lld %lld",&x,&y,&z); g[x][y]=g[y][x]=z;}
scanf("%lld",&D);
for (ll i=1;i<=D;i++) {
scanf("%lld %lld %lld",&p,&daya,&dayb);
for (ll j=daya;j<=dayb;j++) w[j][++w[j][0]]=p;
}
}
int main() {
read();
init();
dp();
return 0;
}

浙公网安备 33010602011771号