样例输入
5 5 10 8 1 2 1 1 3 3 1 4 2 2 3 2 2 4 4 3 4 1 3 5 2 4 5 2 4 2 2 3 3 1 1 3 3 3 4 4 5
样例输出
32
首先,这道题涉及最短路是肯定看得出来。
但是呢,到底该怎么处理有些路不能走的情况呢?
这个时候,我想到了最短路和次短路,用类似树 $dp$ 的办法对其进行处理。
但是这样想有个 $bug$ ,那就是万一最短路和次短路都走不通的情况呢?
然后我就开始疯狂幻想次次短路、次次次短路......
我在考虑这道题的时候,忽略了这道题的数据范围:$n(1\le n\le 100),m(1\le m\le 20)$
可以看出 $n$ 和 $m$ 都是很小的,那么我们为什么不直接暴力做呢。
但是这个暴力也是基于 $dp$ 的基础上的。
首先可以设一个简单的状态:
$dp[i]$:到第 $i$ 天所用的最小花费
那么状转呼之而出
$dp[i]=dp[j]+cost[j+1][i]*(i-j)+K$
其中, $j$ 是我们改变航道的那天。此状转的意思就是从第 $j$ 天开始更换新的航道,由第 $j+1$ 天到第 $i$ 天用同一个航道,前 $j$ 天怎么走的不管,因为这是前面处理的事情,对于我们现阶段不影响。
那么现在只剩一个问题:$cost[i][j]$ 怎么求呢?
从定义入手:
$cost[i][j]$:从第 $i$ 天到第 $j$ 天用同一条航道的最小花费。
再回到前面所说的,此题数据范围很小,那么我们可以直接暴力处理出 $cost[i][j]$
那么代码也就出来了
#include<bits/stdc++.h> using namespace std; #define int long long template<class T>inline void qread(T& x){ char c;bool f=false;x=0; while((c=getchar())<‘0‘||‘9‘<c)if(c==‘-‘)f=true; for(x=(c^48);‘0‘<=(c=getchar())&&c<=‘9‘;x=(x<<1)+(x<<3)+(c^48)); if(f)x=-x; } template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);} inline int rqread(){ char c;bool f=false;int x=0; while((c=getchar())<‘0‘||‘9‘<c)if(c==‘-‘)f=true; for(x=(c^48);‘0‘<=(c=getchar())&&c<=‘9‘;x=(x<<1)+(x<<3)+(c^48)); return f?-x:x; } template<class T>inline T Max(const T x,const T y){return x>y?x:y;} template<class T>inline T Min(const T x,const T y){return x<y?x:y;} template<class T>inline T fab(const T x){return x>0?x:-x;} const int MAXN=100; const int MAXM=20; class gragh{ #define EDGE_SIZE 400 #define NODE_SIZE 20 #define INF 0x3f3f3f3f public: int N,M; struct edge{int to,nxt,w; edge(){} edge(const int T,const int Nx,const int W):to(T),nxt(Nx),w(W){} }e[EDGE_SIZE+5]; int tail[NODE_SIZE+5],ind; inline void add_edge(const int u,const int to,const int w){e[++ind]=edge(to,tail[u],w);tail[u]=ind;} inline void dijkstra(int dis[],const int s,bool vis[]){ struct node{int u,w; node(){} node(const int U,const int W):u(U),w(W){} bool operator<(const node a)const{return !(w<a.w);} }; for(int i=1;i<=N;++i)dis[i]=INF; priority_queue<node>Q; Q.push(node(s,dis[s]=0)); while(!Q.empty()){ int u=Q.top().u;Q.pop(); for(int i=tail[u],v;i;i=e[i].nxt)if(dis[v=e[i].to]>dis[u]+e[i].w&&!vis[v]) Q.push(node(v,(dis[v]=dis[u]+e[i].w))); } } inline bool spfa(int dis[],const int s,bool vis[]){ int cnt[NODE_SIZE+5];/*bool vis[EDGE_SIZE+5];*/ queue<int>Q; for(int i=1;i<=N;++i)dis[i]=INF/*,vis[i]=false*/,cnt[i]=0; Q.push(s); dis[s]=0,cnt[s]=1; while(!Q.empty()){ int now=Q.front();Q.pop(); vis[now]=false,++cnt[now]; if(cnt[now]>N)return false; for(int i=tail[now],v;i;i=e[i].nxt){ v=e[i].to; if(dis[now]+e[i].w<dis[v]){ dis[v]=dis[now]+e[i].w; if(!vis[v])Q.push(v),vis[v]=true; } } } return true; } inline void clr(){memset(tail,ind=0,sizeof tail);} gragh(){clr();} #undef EDGE_SIZE #undef NODE_SIZE #undef INF }G; int n,K,d,cost[MAXN+5][MAXN+5]; bool inf[MAXM+5][MAXN+5]; inline void init(){ qread(n,G.N,K,G.M); for(int i=1,a,b,c;i<=G.M;++i){ qread(a,b,c); G.add_edge(a,b,c); G.add_edge(b,a,c); } qread(d); for(int i=1,P,a,b;i<=d;++i){ qread(P,a,b); for(int j=a;j<=b;++j)inf[P][j]=true; } } void calcCost(){ bool vis[MAXM+5];int dis[MAXM+5]; for(int i=1;i<=n;++i)for(int j=i;j<=n;++j){ memset(vis,0,sizeof vis); for(int k=1;k<=G.N;++k)for(int t=i;t<=j;++t) if(inf[k][t]){vis[k]=true;break;} G.spfa(dis,1,vis); cost[i][j]=dis[G.N]; } } inline void getDp(){ int dp[MAXN+5]; for(int i=1;i<=n;++i)dp[i]=0x3f3f3f3f; for(int i=1;i<=n;++i){ dp[i]=cost[1][i]*i; for(int j=i-1;j>=0;--j) dp[i]=Min(dp[i],dp[j]+cost[j+1][i]*(i-j)+K); } printf("%lld\n",dp[n]); } signed main(){ init(); calcCost(); getDp(); return 0; }
原文:https://www.cnblogs.com/MachineryCountry/p/11653648.html