分析
我们可以对于每一天考虑,如果有一天改了道,那么贪心的选择也应该是最短路,而不是其它的路径。这个还是比较显然的。那么现在考虑一个线性 。令 表示考虑 从第 天的最小代价和。那么转移为 。这里引入了一个 的数组。这里表示从第 天到第 天的合法的最短路。那么我们可以先预处理 总的复杂度为 。最后 的复杂度为 。
代码
#include<bits/stdc++.h> using namespace std; const int N = 201; #define LL long long const int inf = 0x3f3f3f3f; int read() { int x = 0,f = 0;char ch = getchar(); while(!isdigit(ch)) {if(ch=='-')f=1;ch = getchar();} while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();} return f?-x:x; } #define piiL pair<LL,int> #define piii pair<int,int> LL f[N]; int g[N][N],dis[21]; int L[N],R[N],id[N],n,m,K,E; bool vis[21]; vector<piii>G[N]; priority_queue<piiL> q; void solve(int s){ memset(dis,0x3f,sizeof(dis)); dis[s]=0;q.push(piiL(dis[s],s));while(!q.empty()){ int x=q.top().second;q.pop();if(vis[x])continue;vis[x]=1; for(auto e:G[x]) {if(vis[e.first] || dis[e.first]<=dis[x]+e.second) continue; dis[e.first]=dis[x]+e.second;q.push(piiL(-dis[e.first],e.first)); } } } int main() { n=read();m=read();K=read();E=read(); for(int i=1,a,b,c;i<=E;i++){ a=read();b=read();c=read(); G[a].push_back(piii(b,c));G[b].push_back(piii(a,c)); } int T=read();for(int i=1;i<=T;i++)id[i]=read(),L[i]=read(),R[i]=read(); f[0]=0; for(int l=1;l<=n;l++){ for(int r=l;r<=n;r++){ memset(vis,0,sizeof(vis)); for(int k=1;k<=T;k++) if(!(r<L[k]||l>R[k]))vis[id[k]]=1; solve(1);g[l][r]=dis[m]; } } for(int i=1;i<=n;i++){ if(g[1][i]<inf)f[i]=g[1][i]*i; else f[i]=1e18; for(int j=1;j<=i;j++){ if(g[j][i]<inf)f[i]=min(f[i],f[j-1]+g[j][i]*(i-j+1)+K); } } cout<<f[n]<<endl; }