1267: 旅行商问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 53 解决: 6
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
旅行商问题是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP难问题,在运筹学和理论计算机科学中非常重要。
--摘自百度百科
输入
第一行一个正整数n表示城市数量。(n <= 13)
接下来输入一个n行n列邻接矩阵,第i行j列一个非负整数d表示城市i到j的距离。(d <= 1e7)
保证城市i到j的距离等于城市j到i的距离且到自身距离为0。
输出
输出一个非负整数表示经过每个城市一次且仅一次并回到起点的最短距离。
样例输入 Copy
4 0 5 9 4 5 0 13 2 9 13 0 7 4 2 7 0
样例输出 Copy
23
来源/分类
import java.util.*;
//1267
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 城市数量
int[][] distance = new int[n][n]; // 邻接矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
distance[i][j] = scanner.nextInt();
}
}
int[][] dp = new int[1 << n][n]; // dp数组,表示从起点出发,经过某些城市,到达城市i的最短距离
for (int i = 0; i < (1 << n); i++) {
Arrays.fill(dp[i], Integer.MAX_VALUE / 2); // 初始化为最大值
}
dp[1][0] = 0; // 起点到达起点距离为0
// 动态规划求解
for (int mask = 1; mask < (1 << n); mask++) { // mask表示经过的城市集合的状态
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 1) { // 如果城市i在mask中
for (int j = 0; j < n; j++) {
if (((mask >> j) & 1) == 0) { // 如果城市j不在mask中
dp[mask | (1 << j)][j] = Math.min(dp[mask | (1 << j)][j], dp[mask][i] + distance[i][j]);
}
}
}
}
}
// 找到经过所有城市一次且仅一次并回到起点的最短距离
int minDistance = Integer.MAX_VALUE;
for (int i = 0; i < n; i++) {
minDistance = Math.min(minDistance, dp[(1 << n) - 1][i] + distance[i][0]);
}
System.out.println(minDistance);
}
}