Problem
Mean
参见题目描述。
Analysis
动态规划+最短路。
状态转移方程为f[i]=min(f[j-1]+d[m]*(i-j+1)+k),1≤j≤i≤n。d[m]为每次状态转移计算所得当前可行的最短路花费。
Code
#include<cstdio>
#include<utility>
#include<vector>
#include<queue>
using namespace std;
typedef pair<int,int> P;
const int D=2005,N=25,M=405,INF=~0U>>8;
int n,m,k,e,d,ed,x,y,z,f[105],v[M],w[M],nxt[M],g[N],p[D],l[D],r[D],c[N];
priority_queue<P,vector<P>,greater<P> > Q;
int min(int a,int b){return a<b?a:b;}
void addedge(int x,int y,int z){
v[++ed]=y,w[ed]=z;
nxt[ed]=g[x];
g[x]=ed;
}
void dij(int x,int y){
bool enable[N];
for(int i=1;i<=m;i++) enable[i]=1;
for(int i=0;i<d;i++) if(!(x>r[i] || y<l[i])) enable[p[i]]=0;
for(int i=2;i<=m;i++) c[i]=INF;Q.push(P(c[1]=0,1));
while(!Q.empty()){
P t=Q.top();Q.pop();
if(c[x=t.second]<t.first) continue;
for(int i=g[x];i;i=nxt[i]) if(enable[v[i]] && c[x]+w[i]<c[v[i]]) Q.push(P(c[v[i]]=c[x]+w[i],v[i]));
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&e);
for(int i=0;i<e;i++){
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z),addedge(y,x,z);
}
scanf("%d",&d);
for(int i=0;i<d;i++) scanf("%d%d%d",&p[i],&l[i],&r[i]);
for(int i=1;i<=n;i++) f[i]=INF;f[0]=-k;
for(int i=1;i<=n;i++) for(int j=1;j<=i;j++){
dij(j,i);
f[i]=min(f[i],f[j-1]+c[m]*(i-j+1)+k);
}
printf("%d",f[n]);
return 0;
}