旅行商问题——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;
}
}