挺水的。预处理一下一段时间内的最短路,dp即可
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=105,M=25;
bool tong[N][M],vis[M],tt[M];
int dp[N],ycl[N][N],son[M],nedge,n,m,K,E,P,s1,s2,s3,dist[M],oo=1000000000,que[M];
struct edge{
int nextt,ed,di;
}e[810];
inline void aedge(int a,int b,int c){
e[++nedge].nextt=son[a];
son[a]=nedge;
e[nedge].ed=b;
e[nedge].di=c;
}
inline int read()//不管是正负数,都可以
{
int x = 0; char ch = getchar(); bool positive = 1;
for (; !isdigit(ch); ch = getchar()) if (ch == '-') positive = 0;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return positive ? x : -x;
}
inline void write(int a){
if(a>=10)write(a/10);
putchar('0'+a%10);
}
inline void writeln(int a){
write(a); puts("");
}
int spfa(int s,int t,int day1,int day2){int i;
for(i=1;i<=m;i++){dist[i]=oo;vis[i]=que[i-1]=tt[i]=0;}
for(i=day1;i<=day2;i++)for(int j=1;j<=m;j++)tt[j]|=tong[i][j];
int tot=1; int l=0; int r=0; que[0]=s; vis[s]=true; dist[s]=0;
while(tot){
int k=que[l]; //if(day==4)cout<<k<<" "<<tong[4][5]<<endl;
vis[k]=false;
if (++l==m) l=0;
tot--; i=son[k];
while (i) {
if (dist[e[i].ed]>dist[k]+e[i].di&&(!tt[e[i].ed]))
{
dist[e[i].ed]=dist[k]+e[i].di;
if (vis[e[i].ed]==0) {
r++; r%=m;
que[r]=e[i].ed; tot++; vis[e[i].ed]=true;
}
}
i=e[i].nextt;
}
}
return dist[t];
}
int main(){
n=read(); m=read(); K=read(); E=read();
for(int i=1;i<=E;i++){
s1=read(); s2=read(); s3=read(); aedge(s1,s2,s3); aedge(s2,s1,s3);
}
P=read();
for(int i=1;i<=P;i++){
s1=read(); s2=read(); s3=read();
for(int j=s2;j<=s3;j++)tong[j][s1]=true;
}
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)ycl[i][j]=spfa(1,m,i,j);
dp[0]=-K;
for(int i=1;i<=n;i++){dp[i]=oo;
for(int j=0;j<i;j++){
if(ycl[j+1][i]<=(oo>>1))dp[i]=min(dp[i],dp[j]+K+ycl[j+1][i]*(i-j));
}
//cout<<dp[i]<<" "<<i<<endl;
}
cout<<dp[n]<<endl;
}