# 5、状态压缩DP &蒙德里安的梦想 &最短Hamilton路径
# AcWing 291. 蒙德里安的梦想
# AcWing 91. 最短Hamilton路径
import java.util.*;
import java.util.concurrent.LinkedTransferQueue;
//ACWing
public class Main {
public static void main(String[] args) {
Main main = new Main();
main.init();
}
int N = 12,M=1<<N;
boolean st[] = new boolean[M];
long f[][] = new long[N][M];
void init() {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt(), M = sc.nextInt();
while (N != 0 && M != 0) {
for (int i = 0; i < (1 << N); i++) {
st[i] = true;
int cnt = 0;
for (int j = 0; j < N; j++) {
if (((i >> j) & 1) != 0) {
if ((cnt & 1) != 0) {
st[i] = false;
break;
}
} else cnt++;
}
if ((cnt & 1) != 0) st[i] = false;
}
for (int i = 0; i < f.length; i++) {
Arrays.fill(f[i], 0);
}
f[0][0] = 1;
for (int i = 1; i <= M; i++)
for (int j = 0; j < 1 << N; j++)
for (int k = 0; k < 1 << N; k++)
if ((j & k) == 0 && st[j | k])
f[i][j] += f[i - 1][k];
System.out.println(f[M][0]);
N = sc.nextInt();
M = sc.nextInt();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int N = 20,M = 1 << N;
int[][] f = new int[M][N];//当前的状态是i,然后走到了点j上面
int[][] w = new int[N][N];
int n = scan.nextInt();
for(int i = 0 ; i < n ; i ++ )
for(int j = 0 ; j < n ; j ++ )
w[i][j] = scan.nextInt(); // 输入每一步的权重
for(int i = 0 ; i < 1 << n ; i ++ )
Arrays.fill(f[i],0x3f3f3f); //除了第一个点,其他点初始化成正无穷
f[1][0] = 0;
//首先枚举一下所有的状态
for(int state = 0 ; state < 1 << n ; state ++ ){
//一共有多少步
for(int j = 0 ; j < n ; j ++ ){
// 表示能够走到j,才能进行下一步
if((state >> j & 1) == 1){
//我们用倒数第二步来化整为零
for(int k = 0 ; k < n ; k ++ ){
//首先减掉最后一个点剩下的路径中要能够走到k才能够进行状态计算
if((state - (1 << j) >> k & 1) == 1){
//0 - k - j的途径 f[state - (1 << j)][k] + w[k][j]
f[state][j] = Math.min(f[state][j],f[state - (1 << j)][k] + w[k][j]);
}
}
}
}
}
//最后输出从定义出发,不难想到,f[state][j],state表示的是二进制的全0表示都走过,j表示从0走到n-1
System.out.println(f[(1 << n) - 1][n - 1]);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
← 5、树形DP 5、线性dp &数字三角形 →