zoukankan      html  css  js  c++  java
  • [hdu5418 Victor and World]floyd + 状压DP 或 SPFA

    题意:给n个点,m条边,每次只能沿边走,花费为边权值,求从1出发经过所有其它点≥1次最后回到1的最小花费。

    思路:

    1. 状压DP。先用Floyd得到任意两点间的最短距离,转移时沿两个点的最短路转移。此时的状态表示为dp[i][j]:“落脚点集合为i,最后停在j”的方案数;而不是“访问过的点的集合为i,最后停在j”的方案数。
    2. SPFA。每个状态保存访问过的点的集合,以及最后停留的位置,然后SPFA即可。

    floyd + 状压DP

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    #pragma comment(linker, "/STACK:10240000")
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define fillarray(a, b)     memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    #ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    #endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    
    const double PI = acos(-1.0);
    const int INF = 0x3f3f3f3f;
    const double EPS = 1e-12;
    
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 16;
    
    int e[maxn][maxn], dist[maxn][maxn], dp[1 << maxn][maxn];
    int n;
    
    void add(int u, int v, int w) {
        umin(e[u][v], w);
    }
    
    void work() {
        fillchar(dp, 0x3f);
        for (int i = 0; i < n; i ++) {
            for (int j = 0; j < n; j ++) {
                dist[i][j] = e[i][j];
            }
        }
        for (int k = 0; k < n; k ++) {
            for (int i = 0; i < n; i ++) {
                for (int j = 0; j < n; j ++) {
                    if (k != i && k != j && i != j) {
                        umin(dist[i][j], dist[i][k] + dist[k][j]);
                    }
                }
            }
        }
        dp[1][0] = 0;
        for (int i = 2; i < (1 << n); i ++) {
            for (int j = 0; j < n; j ++) {
                if (i & (1 << j)) {
                    for (int k = 0; k < n; k ++) {
                        if (k != j) if (i & (1 << k)) {
                            umin(dp[i][j], dp[i ^ (1 << j)][k] + dist[k][j]);
                        }
                    }
                }
            }
        }
        int ans = dp[(1 << n) - 1][0];
        for (int i = 1; i < n; i ++) {
            umin(ans, dp[(1 << n) - 1][i] + dist[i][0]);
        }
        cout << ans << endl;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, u, v, w, m;
        cin >> T;
        while (T --) {
            cin >> n >> m;
            fillchar(e, 0x3f);
            for (int i = 0; i < m; i ++) {
                scanf("%d%d%d", &u, &v, &w);
                u --; v --;
                add(u, v, w);
                add(v, u, w);
            }
            work();
        }
        return 0;
    }
    

    SPFA:

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    #pragma comment(linker, "/STACK:10240000")
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define fillarray(a, b)     memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    #ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    #endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    
    const double PI = acos(-1.0);
    const int INF = 0x3f3f3f3f;
    const double EPS = 1e-12;
    
    /* -------------------------------------------------------------------------------- */
    
    const int maxn = 16;
    
    int n;
    int e[maxn][maxn], d[maxn][1 << maxn], vis[maxn][1 << maxn];
    
    void add(int u, int v, int w) {
        u --;
        v --;
        umin(e[u][v], w);
    }
    
    bool relax(pii u, pii v, int w) {
        if (d[v.X][v.Y] > d[u.X][u.Y] + w) {
            d[v.X][v.Y] = d[u.X][u.Y] + w;
            return true;
        }
        return false;
    }
    
    void work() {
        fillchar(vis, 0);
        fillchar(d, 0x3f);
        queue<pii> Q;
        Q.push(mp(0, 1));
        d[0][1] = 0;
        vis[0][1] = true;
        while (!Q.empty()) {
            pii H = Q.front(); Q.pop();
            vis[H.X][H.Y] = false;
            for (int i = 0; i < n; i ++) {
                if (e[H.X][i] < INF) {
                    pii P = mp(i, H.Y | (1 << i));
                    if (relax(H, P, e[H.X][i]) && !vis[P.X][P.Y]) {
                        vis[P.X][P.Y] = true;
                        Q.push(P);
                    }
                }
            }
        }
        cout << d[0][(1 << n) - 1] << endl;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, u, v, w, m;
        cin >> T;
        while (T --) {
            cin >> n >> m;
            fillchar(e, 0x3f);
            for (int i = 0; i < m; i ++) {
                scanf("%d%d%d", &u, &v, &w);
                add(u, v, w);
                add(v, u, w);
            }
            work();
        }
        return 0;
    }
    
  • 相关阅读:
    随机二分图
    城市旅行
    JZPKIL
    线性基专题总结
    杜教筛专题总结
    [NOI2018]你的名字
    P1120 小木棍 [数据加强版]
    先序遍历
    P1736 创意吃鱼法
    P2258 子矩阵
  • 原文地址:https://www.cnblogs.com/jklongint/p/4751856.html
Copyright © 2011-2022 走看看