很神經的一道題。
令 \(val_{i,j}\) 表示從第 \(i\) 天到第 \(j\) 天每天都走一條道路,單次的最小花費。可以列舉 \(\{i,j\}\) 然後把在這個區間裡的所有點設定成不可達,每一個 \(\{i,j\}\) 都可以用 floyd 算,時間複雜度 \(O(n^2m^3)\)。
令 \(f_i\) 表示第 \(i\) 天的最小花費,那麼我們有 \(f_i=\min_{j=1}^{i-1}(f_j+val_{j+1,i}\times (j-i)+k)\)。
點選檢視程式碼
#include<bits/stdc++.h>
#define int ll
#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define inn(i,n,a) For(i,1,n) a[i]=read();
#define ll long long
#define i128 __int128
using namespace std;
inline int read() {
int xx= 0;int f= 1;
char c = getchar();
while(c<'0'||c>'9') {
if(c=='-') f= -1;
c= getchar();
}
while(c>='0'&&c<='9') {
xx= (xx<<1)+(xx<<3)+(c^48);
c= getchar();
}
return xx*f;
}
#define maxn 200050
int G[22][22];
int val[110][110];
int n,m,k,e;
vector<int> g[110];
int dis[22][22];
bool vis[22];
ll dp[110];
void pre_dis(int l,int r) {
m0(vis);
For(i,1,m) For(j,1,m) dis[i][j]=G[i][j];
For(i,1,m) dis[i][i]=0;
For(i,l,r) {
for(auto u:g[i])
vis[u]=1;
}
For(i,1,m) {
if(vis[i]) {
For(j,1,m) dis[i][j]=1e9,dis[j][i]=1e9;
}
}
For(k,1,m) For(i,1,m) For(j,1,m) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
val[l][r]=dis[1][m];
}
signed main() {
in2(n,m); in2(k,e);
mem(G,0x3f);
For(i,1,e) {
int u,v,d;
in3(u,v,d);
G[u][v]=G[v][u]=min(G[u][v],d);
}
int _=read();
while(_--) {
int p,a,b;
in3(p,a,b);
For(i,a,b) g[i].push_back(p);
}
For(i,1,n) For(j,i,n)
pre_dis(i,j);
For(i,1,n) {
dp[i]=val[1][i]*i;
For(j,1,i-1)
dp[i]=min(dp[i],dp[j]+val[j+1][i]*(i-j)+k);
}
cout<<dp[n];
}