题意:
在一个n点m边的带权无向图上从ai走到bi做k个任务,求最小花费。
可以在当点随时建立一个传送门,或者关闭任一点一个传送门,传送门数量不大于两个
通过传送门从u传送到v花费为0
做法:
通过Floyd预处理出每两个点之间的距离
考虑动态规划来解决最小花费问题
f[i][j] 表示完成i个任务时,当前位置在a[i]上,传送门在j处的最小花费
转移有:
1.直接从a[i]走到a[i+1]
2.枚举走到a[i+1]之后,传送门的位置变为了哪个节点,设这个节点是q。第二种转移是从a[i]走到q,在q设置传送门,从q传送到p,再从p走到a[i+1]
3.第三种转移是从a[i]传送到p,从p走到q,在q设置传送门,最后从q走到a[i+1]
最后遍历一遍完成k个任务后,取传送门在1~n的最小花费即可
CODE
1 #include <bits/stdc++.h> 2 #define dbug(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5 6 using namespace std; 7 typedef long long LL; 8 9 const int inf = 0x3f3f3f3f; 10 11 template<class T>inline void read(T &res) 12 { 13 char c;T flag=1; 14 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 15 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 16 } 17 18 const int maxn = 1e3 + 7; 19 20 int n, m, k; 21 LL a[maxn]; 22 LL f[maxn][maxn]; 23 24 LL dis[maxn][maxn]; 25 26 int main() 27 { 28 memset(dis, inf, sizeof(dis)); 29 read(n); read(m); read(k); 30 for ( int i = 1; i <= n; ++i ) { 31 dis[i][i] = 0; 32 } 33 for ( int i = 1; i <= m; ++i ) { 34 int u, v, w; 35 read(u); read(v); read(w); 36 dis[u][v] = dis[v][u] = min(dis[u][v], min(1ll * w, dis[v][u])); 37 } 38 for ( int k = 1; k <= n; ++k ) { 39 for ( int i = 1; i <= n; ++i ) { 40 for ( int j = 1; j <= n; ++j ) { 41 if(i == j) { 42 dis[i][j] = dis[j][i] = 0; 43 } 44 else { 45 if(dis[i][k] + dis[k][j] < dis[i][j]) { 46 dis[i][j] = dis[i][k] + dis[k][j]; 47 } 48 } 49 } 50 } 51 } 52 memset(f, inf, sizeof(f)); 53 // for ( int i = 1; i <= n; ++i ) { 54 // f[1][i] = inf; 55 // } 56 int p = k << 1; 57 for ( int i = 1; i <= p; ++i ) { 58 read(a[i]); 59 } 60 for ( int i = 1; i <= n; ++i ) { 61 f[1][i] = INT64_MAX; 62 } 63 f[0][1] = 0; 64 a[0] = 1; 65 for ( int i = 1; i <= p; ++i ) { 66 for ( int j = 1; j <= n; ++j ) { 67 f[i][j] = min(f[i][j], f[i - 1][j] + dis[a[i - 1]][a[i]]); 68 f[i][j] = min(f[i][j], f[i - 1][j] + dis[j][a[i]]); 69 for ( int z = 1; z <= n; ++z ) { 70 f[i][z] = min(f[i][z], f[i - 1][j] + dis[a[i - 1]][z] + dis[z][a[i]]); 71 f[i][z] = min(f[i][z], f[i - 1][j] + dis[a[i - 1]][z] + dis[j][a[i]]); 72 f[i][z] = min(f[i][z], f[i - 1][j] + dis[j][z] + dis[z][a[i]]); 73 } 74 } 75 } 76 // for ( int i = 1; i <= p; ++i ) { 77 // for ( int j = 1; j <= n; ++j ) { 78 // printf("f[%d][%d]:%d ",i, j, f[i][j]); 79 // } 80 // } 81 LL ans = INT64_MAX; 82 for ( int i = 1; i <= n; ++i ) { 83 ans = min(1ll * f[p][i], ans); 84 } 85 cout << ans << endl; 86 return 0; 87 }