傳送門
題解:
由由於天的數量的只有100,而且只有20個港口,數據量很小。所以,能夠直接用最短路預處理第i天到第j天用同一種路徑所須要的花費。而後,預處理以後,用一個簡單的dp就能夠了。\(dp[i]=min(dp[j]+cost[j+1][i]+k)\)其中\(dp[i]\)表示到第i天的最小花費,\(cost[i][j]\)第i天到第j天用同一種路徑所須要的花費,k是換方案的費用。php
#include<bits/stdc++.h> using namespace std; const int maxn=2e4+50; const int inf = 2e9; long long cost[25]; long long c[105][105]; bool vis[25]; long long dp[105]; bool vis0[25][105]; bool flag[105]; struct node { int id,dis; node(int x):id(x),dis(cost[x]){}; bool operator<(const node& b)const { return dis<b.dis; } }; struct edge { int next,to,w; }e[maxn]; int head[maxn*2],tot; void add(int u,int v,int w) { e[tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } void dijkstra(int n) { //memset(vis,0,sizeof(vis)); memset(cost,0x7f,sizeof(cost)); cost[1]=0; priority_queue<node>Q; Q.push(node(1)); while(!Q.empty()) { node temp=Q.top(); vis[temp.id]=1; Q.pop(); for(int i=head[temp.id];i!=-1;i=e[i].next) { //if(vis[e[i].to]) continue; if(cost[temp.id]+e[i].w<cost[e[i].to]&&!flag[e[i].to]) { cost[e[i].to]=cost[temp.id]+e[i].w; Q.push(node(e[i].to)); } } } } int main() { memset(head,-1,sizeof(head)); int i,j,n,m,k,N,M; cin>>n>>m>>k>>N; int w,u,v; for(i=0;i<N;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } cin>>M; for(i=0;i<M;i++) { scanf("%d%d%d",&w,&u,&v); for(j=u;j<=v;j++) vis0[w][j]=1; } for(i=1;i<=n;i++) { for(j=i;j<=n;j++) { memset(flag,0,sizeof(flag)); for(int k=1;k<=m;k++) { for(int s=i;s<=j;s++) flag[k]|=vis0[k][s]; } dijkstra(m); //cout<<cost[m]<<endl; c[i][j]=cost[m]; } } for(i=1;i<=n;i++) for(j=i;j<=n;j++) if(c[i][j]<inf) c[i][j]*=1ll*(j-i+1); memset(dp,0x7f,sizeof(dp)); for(i=1;i<=n;i++) dp[i]=c[1][i]; for(i=2;i<=n;i++) { for(j=1;j<i;j++) { dp[i]=min(dp[i],dp[j]+c[j+1][i]+k); } } cout<<dp[n]<<endl; }