[集合DP] 货郎担问题 TSP的DP做法

题目

这里写图片描述
(目前比较流行的说法是叫旅行商问题)

思路

直接规定起点和终点都是城市0。(原因慢慢想)
1.状态定义:d(i,S),当前处于i城市,还需访问S中的城市各一次最后回到城市0的最短长度。
2.边界:d(i,{}) = dist(0,i)
3.答案:d(0, {1,2,3,…,n-1})
4.状态转移方程:

d ( i , S ) = m i n { d ( j , S { j } + d i s t ( i , j ) | j S }

5.时间复杂度: O ( n 2 2 n ) (理论上)

代码

(代码没有进行过测试)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 15 + 1;
const int maxsum = 1 << 16;
const int INF = 1 << 20;
int n, G[maxn][maxn], d[maxn][maxsum];

void dp(int i, int S) {
    if (S == 0) {
        d[i][S] = G[0][i];
        return;
    }
    d[i][S] = INF;
    _for(j, 0, n)
        if (S & (1 << j))
            d[i][S] = min(d[i][S], d[j][S ^ (1 << j)] + G[i][j]);
}

int main() {
    scanf("%d", &n);
    _for(i, 0, n)  // 理想输入
        _for(j, 0, n)
            scanf("%d", &G[i][j]);

    dp(0, (1 << n) - 1);
    printf("%d\n", d[0][(1 << n) - 1 - 1]);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/icecab/article/details/80991664