物流运输
物流运输
基础dp题+最短路,就是细节有点多
dp方程:设f[i]表示前i天的最少成本
则 f[i]=min(f[i], f[j] + k + (i-j) * w(j+1,i) ) (j<i)
细节1:区分清楚n和m
细节2:枚举j时倒序枚举,方便求最短路时知道哪些码头不能通过
细节3:dp[0]= - k (第一次走最短路不需要成本)
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define Maxn 2500
#define Maxm 9000
#define Inf 2e9
#define mp make_pair
#define pr pair<int,int>
int n,m,k,e;
int fir[Maxn],nxt[Maxm],vv[Maxm],edge[Maxm];
int tot=0;
void add(int x,int y,int z)
{
nxt[++tot]=fir[x];
fir[x]=tot;
vv[tot]=y;
edge[tot]=z;
}
int a[110][Maxn];
int dp[Maxn];
int dis[Maxn],vis[Maxn],now[Maxn];
priority_queue<pr,vector<pr>,greater<pr> >q;
int cost()
{
for(int i=1;i<=m;i++)dis[i]=Inf;
for(int i=1;i<=m;i++)vis[i]=0;
dis[1]=0;
q.push(mp(0,1));
while(!q.empty())
{
pr tmp=q.top();q.pop();
int u=tmp.second;
if(vis[u])continue;
vis[u]=1;
for(int i=fir[u];i;i=nxt[i])
{
int v=vv[i];
if(now[v]==1)continue;
if(dis[v]>dis[u]+edge[i])
{
dis[v]=dis[u]+edge[i];
q.push(mp(dis[v],v));
}
}
}
return dis[m];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&e);
for(int i=1;i<=e;i++)
{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
int dd;scanf("%d",&dd);
for(int i=1;i<=dd;i++)
{
int P;scanf("%d",&P);
int st,ed;
scanf("%d%d",&st,&ed);
for(int j=st;j<=ed;j++)a[j][P]=1;
}
for(int i=1;i<=m;i++)dp[i]=Inf;
dp[0]=-k;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)now[j]=0;
for(int j=i-1;j>=0;j--)
{
for(int kk=1;kk<=m;kk++)if(a[j+1][kk]==1)now[kk]=1;
int cnt=cost();
if(cnt==Inf)break;
dp[i]=min(dp[i],dp[j]+k+cnt*(i-j));
}
}
printf("%d",dp[n]);
return 0;
}