牛客多校五 A.portal【dp|Floyd】

题意:

  在一个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\n",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 }

 

posted @ 2020-07-31 15:18  Orangeko  阅读(187)  评论(0编辑  收藏  举报