/*
- Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved.
*/
/**
-
状态压缩dp
*/
public class SC {public static void main(String[] args) {
int[][] grass = {{1,1},{1,1}};
System.out.println(num(grass));
}// 状态压缩三步走
private static long num(int[][] grass) {
// 前置确定:要生成几进制数
// grass每个土地有七种情况,因此是七进制,移位以3为单位
// 第一步,获取每一行的地形
int[] gr = new int[grass.length];
for (int i = 0;i < gr.length;i++) {
for (int j = 0;j < grass[0].length;j++) {
gr[i] = (gr[i] << 3) + grass[i][j];
}
}
// 第二步,获取通用的方案数
// 如何判断进制的问题还有待商榷
boolean[] scheme = new boolean[1 << (grass[0].length * 3)];
for (int i = 0;i < scheme.length;i++) {
if (isSeven(i) && noSame(i, i << 3)) {
scheme[i] = true;
}
}
// 第三步,逐行逐方案生成dp
int[][] dp = new int[grass.length + 1][1 << (grass[0].length * 3)];
dp[0][0] = 1;
for (int i = 1;i < dp.length;i++) {
for (int j = 0;j < dp[0].length;j++) {
// 要判断两个问题:当前方案是否符合地形,当前方案是否与上一行方案兼容
if (scheme[j] && isSuit(j, gr[i - 1])) {
for (int k = 0;k < scheme.length;k++) {
if (noSame(j, k)) {
dp[i][j] += dp[i - 1][k];
dp[i][j] %= 100000000;
}
}
}
}
}
long ans = 0;
for (int i = 0;i < dp[0].length;i++) {
ans += dp[dp.length - 1][i];
ans %= 100000000;
}
return ans;
}
// 判断i是否是七进制数
private static boolean isSeven(int i) {
while (i != 0) {
if ((i & 7) == 7) {
return false;
}
i = i >> 3;
}
return true;
}
// 判断i方案和j方案是否有相同的植物
private static boolean noSame(int i, int j) {
while (i != 0 && j != 0) {
if ((i & 7) != 0 && (i & 7) == (j & 7)) {
return false;
}
i = i >> 3;
j = j >> 3;
}
return true;
}
// 判断i是否符合地形j
private static boolean isSuit(int i, int j) {
// 主要是判断j中000的部分i是否也是000以及不是000的部分是否是000
while (i != 0 && j != 0) {
if ((j & 7) == 0 && (i & 7) != (j & 7)) {
return false;
} else if ((j & 7) != 0 && (i & 7) == 0) {
return false;
}
i = i >> 3;
j = j >> 3;
}
return true;
}
}