• 牛客多校五 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
    ",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 }
  • 相关阅读:
    法里数列
    母函数笔记
    贝尔数的指数母函数推导
    jQuery监听文本框值改变触发事件(propertychange)
    java-->TreeMap的使用
    查找-->二分查找和插值查找java实现
    查找-->斐波那契查找算法
    排序-->归并排序
    希尔排序(交换法和位移法)
    8皇后算法的简单实现(回溯)
  • 原文地址:https://www.cnblogs.com/orangeko/p/13409884.html
Copyright © 2020-2023  润新知