Code:
定义状态 $dp[i]$ 为前 $i$ 天的最小代价。
状态转移为:$dp[i]=min(dp[i],dp[j]+spfa(j+1,i)$ 这里 $spfa(i,j)$ 是指 $(i,j)$ 天中用一种最短路方案的最短路(最小花费)
#include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<deque> using namespace std; void setIO(string a){ freopen((a+".in").c_str(),"r",stdin); } const int maxn=30; const int inf=10000000; int n,m; int tag[maxn],head[maxn], to[1000000], nex[1000000],val[1000000],edges; int a[maxn][200]; long long dp[200]; void add_edge(int u,int v,int c){ nex[++edges]=head[u], head[u]=edges, to[edges]=v, val[edges]=c; } deque<int>Q; bool inq[100000]; int d[maxn]; int spfa(int l,int r){ Q.clear(); for(int i=0;i<maxn;++i) d[i]=inf; memset(tag,0,sizeof(tag)); memset(inq,false,sizeof(inq)); for(int i=1;i<=m;++i) for(int j=l;j<=r;++j) if(a[i][j]) tag[i]=1; Q.push_back(1); d[1]=0,inq[1]=true; while(!Q.empty()){ int u=Q.front(); Q.pop_front(); inq[u]=false; for(int v=head[u];v;v=nex[v]){ if(tag[to[v]]) continue; if(d[u]+val[v] < d[to[v]]){ d[to[v]]=d[u]+val[v]; if(!inq[to[v]]){ if(Q.empty()||d[to[v]]<=d[Q.front()]) Q.push_front(to[v]); else Q.push_back(to[v]); inq[to[v]]=true; } } } } return d[m]; } void update(long long &a,long long b){ if(b<a)a=b; } int main(){ //setIO("input"); int k,e; scanf("%d%d%d%d",&n,&m,&k,&e); for(int i=1;i<=e;++i){ int a,b,c; scanf("%d%d%d",&a,&b,&c); add_edge(a,b,c); add_edge(b,a,c); } int cnt; scanf("%d",&cnt);// for(int i=1;i<=cnt;++i){ int p,l,r; scanf("%d%d%d",&p,&l,&r); for(int j=l;j<=r;++j) a[p][j]=1; } for(int i=1;i<=n;++i) { dp[i]=spfa(1,i)*i; for(int j=1;j<i;++j) update(dp[i],dp[j]+(long long)spfa(j+1,i)*(i-j)+k); } printf("%lld\n",dp[n]); return 0; }