小明目前在做一份毕业旅行的规划。打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次。由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的花销。给定一组城市和每对城市之间的火车票的价钱,找到每个城市只访问一次并返回起点的最小车费花销。
输入描述:
城市个数n(1<n≤20,包括北京)
城市间的车票价钱 n行n列的矩阵 m[n][n]
输出描述:
最小车费花销 s
示例1
输入
4
0 2 6 5
2 0 4 4
6 4 0 2
5 4 2 0
输出
13
说明
共 4 个城市,城市 1 和城市 1 的车费为0,城市 1 和城市 2 之间的车费为 2,城市 1 和城市 3 之间的车费为 6,城市 1 和城市 4 之间的车费为 5,依次类推。假设任意两个城市之间均有单程票可购买,且票价在1000元以内,无需考虑极端情况。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[][] dist = new int[n][n];
for (int i = 0; i < dist.length; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = in.nextInt();
}
}
in.close();
//随便挑一个作为起点,为方便计算,就选择0城市就好,
// 那么对应的事件可以理解为从0号城市出发去(1号、2号、3号城市)最后回到0号城市,其中中间的1、2、3之间的顺序不清楚怎么去的。
//但是可以发现事件最小消耗为min(从0->1的距离+从1号到{2号、3号}最后回到0的距离、
// 从0->2的距离+从2号到{1号、3号}最后回到0的距离、
// 从0->3的距离+从1号到{1号、2号}最后回到0的距离)。
// 用bit第几位是否为1表示当前事件有哪几号城市。{2号、3号}——> 110;
int V = 1 << (n - 1);
int[][] dp = new int[n][V];
dp[0][0] = 0;
for (int j = 0; j < V; j++) {
for (int i = 0; i < n; i++) {
if (j == 0) {
//表示从第i个城市到第j(0)个城市的最小路径。正好就是第i个城市去第0个城市的距离。
dp[i][j] = dist[i][j] + dp[0][0];
} else {
dp[i][j] = Integer.MAX_VALUE;
for (int k = 1; k < n; k++) {
//表示第k位城市。
int index = (1 << (k - 1));
//当前的dp应该是遍历了j城市集的每一个城市对应的子dp+i到k的距离,求得的其中的最小的那个值;
if ((index & j) > 0) {
//找到其中的一个k;
//表示j城市集内除了第k位其他的别的城市
int other = j ^ index;
dp[i][j] = Math.min(dist[i][k] + dp[k][other], dp[i][j]);
}
}
}
}
}
System.out.println(dp[0][V - 1]);
}
}