zoukankan      html  css  js  c++  java
  • 旅行商问题

    91. 最短Hamilton路径

    题意:旅行商问题,即从 (1) 走到 (n) 不重不漏,然后求最小距离。
    题解:状态压缩dp,显然的是,要从某种状态到某种状态并且合法,然后取 (min),然后全部遍历。所以设 (dp_{i, j}) 的含义是,最后一个点是 (i) 点,然后走过了 (j) 这个 (01) 串的有 (1) 的点。然后要想的是顺序问题,那么我们必然是从上一个点推到 (i) 点,所以可以遍历所有点,然后得到 (k) 点,(k) 点一定是在这个 (j) 里面,然后那么 $$dp_{i, j} = MIN{dp_{i, j}, dp_{k, j - (1 >> i)}}$$。
    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int N = 21;
    int dp[N][1 << N];
    int w[N][N];
    void solve() {
        int n;cin >> n;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> w[i][j];
            }
        }
        memset(dp, 0x3f, sizeof dp);
        dp[0][1] = 0;
        for (int j = 0; j < 1 << n; j++) {
            for (int i = 0; i < n; i++) {
                if ((j >> i) & 1) {
                    for (int k = 0; k < n; k++) {
                        if (((j - (1<<i)) >> k) & 1 ) {
                            dp[i][j] = min(dp[i][j], dp[k][j - (1 << i)] + w[k][i]);
                        }
                    }
                }
            }
        }
        cout << dp[n - 1][(1 << n) - 1] << endl;
    }
    int main() {
        int t = 1;//cin >> t;
        while (t--) solve();
        return 0;
    }
    

    E - Traveling Salesman among Aerial Cities

    题意:旅行商问题裸题,只不过多出来一项操作是不重不漏走完,并且还要回到原点,也没啥,如果理解了旅行商问题的 (dp) 方程代表含义,就很简单。
    代码:

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const ll N = 29;
    
    struct node {
        ll x, y, z;
    }a[22];
    bool check(ll j, ll k, ll n) {
        for (ll i = 0; i < n; i++) {
            if (j >> i & 1) {
                for (ll ii = -1; ii <= 1; ii++) {
                    ll d=  i + ii;
                    d = max((ll)0, d);
                    if ( k >> d  & 1 ) {
                        return 0;
                    }
                }
            }
        }
        return 1;
    }
    
    ll w[N][N];
    ll dp[N][1 << 18];
    void solve() {
        ll n;cin >> n;
        for (ll i = 0; i < n; i++) cin >> a[i].x >> a[i].y >> a[i].z;
        for (ll i = 0; i < n; i++) {
            for (ll j = 0; j < n; j++) 
            {
                if (i == j)continue;
                w[i][j] = abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y) + max((ll)0, a[j].z - a[i].z);
                w[j][i] = abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y) + max((ll)0, a[i].z - a[j].z);
            }
        }
        memset(dp , 0x3f, sizeof dp);
        dp[0][1] = 0;
        for (ll j = 0; j < 1 << n; j++) {
            for (ll i = 0; i < n; i++) {
                for (ll k = 0; k < n; k++) {
                    if ( (j - (1 << i) ) >> k & 1 && (j - (1 << i) )>=0) {
                        dp[i][j] = min(dp[i][j], dp[k][j - (1 << i)] + w[k][i]);
                    }
                }
            }
        }
        ll ans = 0x7fffffff;
        for (ll i = 1; i < n; i++) ans = min(ans, dp[i][ (1 << n) - 1] + w[i][0]);//多出来了这个,就是知道了dp数组含义后,就很简单
        cout << ans << endl;
    }
    signed main() {
        ll t = 1;//cin >> t;
        while (t--) solve();
        return 0;
    }
    
  • 相关阅读:
    LeetCode刷题记录
    开始学习Functional Programming
    明天软软onsite
    Criteo电面二
    Jet.com
    还需要补充很多知识
    重新粗推了一下Master Theorem
    买了第一台mac
    病来如山倒
    Integer.parseInt vs Integer.valueOf
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14501724.html
Copyright © 2011-2022 走看看