dp的方式求最短路
注意:以后对元素赋值为 Integer.MAX_VALUE 判断是否出现溢出的情况,建议以后直接赋值 1e9
/*
状态表示:f[i][j]:所有从0走到j,走过的所有点是i的所有路径 例 i = 10010;可以表示走过第2、5个点
*/
import java.io.*;
class Main {
static int N = 20, M = 1 << N;
static int[][] w = new int[N][N];
static int[][] f = new int[M][N];
public static void main(String[] args) throws IOException {
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
String[] s = cin.readLine().split(" ");
int n = Integer.parseInt(s[0]);
for (int i = 0; i < n; i++) {
s = cin.readLine().split(" ");
for (int j = 0; j < n; j++){
w[i][j] = Integer.parseInt(s[j]);
}
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) f[i][j] = Integer.MAX_VALUE >> 1; // 以后注意赋最大值考虑是否会出现溢出的情况
}
f[1][0] = 0;
for (int i = 0; i < 1 << n; i++) {
for (int j = 0; j < n; j++) {
if ((i >> j & 1) == 1) { //i包含第j个点
for(int k = 0; k < n; k++) { // k表示可以从哪个状态转移而来,
if(((i - (1 << j)) >> k & 1) == 1) { // i 去掉 j 这个点一定包含k这个点才能说明可以从k这个点转移而来
f[i][j] = Math.min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
}
}
}
}
}
System.out.println(f[(1 << n) - 1][n - 1]);
}
}