import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
int c[][] = {
{0, 3, 6, 7},
{5, 0, 2, 3},
{6, 4, 0, 2},
{3, 7, 5, 0}
};
Node node = new Node(c.length);
// 初始化状态
for (int i = 1; i < c.length; i++) {
node.list[i].put(new HashSet<>(), c[i][0]);
}
// 迭代,次数为n - 2次,n为各顶点数
for (int d = 2; d < c.length; d++) {
Node node1 = new Node(c.length);
// i作为入度顶点
for (int i = 1; i < c.length; i++) {
HashMap<Set<Integer>, Integer> item = node.list[i];
if (item.size() == 0) continue;
Set<Set<Integer>> sets = item.keySet();
// j为出发点, j -> i
for (int j = 1; j < c.length; j++) {
// j -> i 如果无路可走就寻找下一个顶点
if (c[j][i] == 0) continue;
int min = Integer.MAX_VALUE;
Set<Integer> set1 = null;
// 寻找保存j -> i时,然后 ->... -> 0的最短路径
for (Set<Integer> set : sets) {
// 如果j已经在已走过的顶点集里则跳过
if (set.contains(j)) continue;
int res = c[j][i] + item.get(set);
if (min > res) {
min = res;
set1 = set;
}
}
HashSet<Integer> set2 = new HashSet<>();
for (Integer integer : set1) {
set2.add(integer);
}
set2.add(i);
HashMap<Set<Integer>, Integer> hm = node1.list[j];
// 保存j -> i .... -> 0 的最短路径长度,如果已有走过的该顶点集,则取最小值
if (hm.containsKey(set2)) {
hm.put(set2, Math.min(hm.get(set2), min));
} else {
hm.put(set2, min);
}
}
}
node = node1;
}
// 最后求出0 -> 各个点的最小值
int min = Integer.MAX_VALUE;
for (int i = 1; i < c.length; i++) {
HashMap<Set<Integer>, Integer> item = node.list[i];
if (item.size() == 0) continue;
Set<Set<Integer>> sets = item.keySet();
if (c[0][i] == 0) continue;
for (Set<Integer> set : sets) {
int res = c[0][i] + item.get(set);
if (min > res) {
min = res;
}
}
}
System.out.println(min);
}
}
class Node {
HashMap<Set<Integer>, Integer>[] list;
public Node(int n) {
this.list = new HashMap[n];
for (int i = 0; i < n; i++) {
list[i] = new HashMap();
}
}
}
时间复杂度相对于暴力的O(N!) 下降到 O(2^n)