旅行商问题——lintcode816(状压dp)

旅行商问题

题目:旅行商问题

给 n 个城市(从 1 到 n),城市和无向道路成本之间的关系为3元组 [A, B, C](在城市 A 和城市 B 之间有一条路,成本是 C)我们需要从1开始找到的旅行所有城市的付出最小的成本。

一个城市只能通过一次。
你可以假设你可以到达所有的城市

示例:

输入: 
n = 3
tuple = [[1,2,1],[2,3,2],[1,3,3]]
输出: 3
说明:最短路是1->2->3

题解:状压dp

转移方程:dp[state][i]=dp[preState][j]+graph[j][i];
state:当前路径状态,如:1—>2—>4
preState: 当前路径的前一个状态:1—>2
则1—>2—>4最小路径=(1—>2—>3)+(3—>4)
public class Solution {
        public int minCost(int n, int[][] roads) {
            int minCost = 1000000000;
            int[][] graph = new int[n + 1][n + 1];

            //构图
            for (int i = 0; i <= n; i++) {
                Arrays.fill(graph[i], minCost);
            }
            for (int i = 0; i < roads.length; i++) {
                graph[roads[i][0]][roads[i][1]] = Math.min(graph[roads[i][0]][roads[i][1]], roads[i][2]);
                graph[roads[i][1]][roads[i][0]] = Math.min(graph[roads[i][1]][roads[i][0]], roads[i][2]);
            }

            int state = 1 << n;
            int[][] dp = new int[state][n + 1];
            for (int i = 0; i < dp.length; i++) {
                Arrays.fill(dp[i], minCost);
            }
            dp[1][1] = 0;

            //状压dp
            for (int s = 0; s < state; s++) {
                for (int i = 2; i <= n; i++) {
                    if ((s & (1 << (i - 1))) == 0) {
                        continue;
                    }
                    int pre = s ^ (1 << (i - 1));
                    for (int j = 1; j <= n; j++) {
                        if ((pre & (1 << (j - 1))) == 0) {
                            continue;
                        }
                        dp[s][i] = Math.min(dp[s][i], dp[pre][j] + graph[j][i]);
                    }
                }
            }

            for (int i = 0; i <= n; i++) {
                minCost = Math.min(minCost, dp[state - 1][i]);
            }
            return minCost;
        }
    }
posted @ 2022-01-09 19:02  言思宁  阅读(97)  评论(0编辑  收藏  举报