#include涂抹果酱using namespace std; const int MOD = 1e8; int m, n; int a[19][19]; int f[19][5000]; bool check(int x, int r) { if (x >> 1 & x) return false; //两块草地有公共边 for (int j = n - 1; j >= 0; j --) { if ((x >> j & 1) && !a[r][j]) { //有土地不适合种草 return false; } } return true; } int main() { cin >> m >> n; for (int i = 1; i <= m; i ++) { for (int j = n - 1; j >= 0; j --) { cin >> a[i][j]; } } f[0][0] = 1; for (int i = 1; i <= m + 1; i ++) { for (int j = 0; j < 1 << n; j ++) { if (!check(j, i)) continue; for (int k = 0; k < 1 << n; k ++) { if (!check(k, i - 1)) continue; if (j & k) continue; //两块草地有公共边 f[i][j] = (f[i][j] + f[i - 1][k]) % MOD; } } } cout << f[m + 1][0]; return 0; }
#include国王using namespace std; const int MOD = 1e6; int n, m; //n行m列 int k, x, num; //第k行的输入对应十进制数num int f[10009][250]; //f[i][j]表示第i行状态为j的方案数 int cnt, a[250]; //有cnt个合法的状态,a[j]是第j个合法状态对应的十进制数 int b[250][5]; //b[j]是第j个合法状态的三进制数 int main() { cin >> n >> m >> k; for (int j = 0; j < pow(3, m); j ++) { a[++ cnt] = j; int t = j; for (int k = 0; k < m; k ++) { b[cnt][k] = t % 3; t /= 3; if (k > 0 && b[cnt][k] == b[cnt][k - 1]) { //状态j不合法 cnt --; break; } } } //当m = 5时,一共只有48个合法的状态 for (int i = 0; i < m; i ++) cin >> x, num = num * 3 + (x - 1); f[0][num] = 1; for (int i = 1; i < n; i ++) { for (int j1 = 1; j1 <= cnt; j1 ++) { //第i行是第j1个合法方案 for (int j2 = 1; j2 <= cnt; j2 ++) { //第i-1行是第j2个合法方案 bool flag = true; for (int k = 0; k < m; k ++) { if (b[j1][k] == b[j2][k]) { flag = false; break; } } if (flag) { f[i][a[j1]] = (f[i][a[j1]] + f[i - 1][a[j2]]) % MOD; } } } } int ans1 = 0, ans2 = 0; for (int j = 1; j <= cnt; j ++) { ans1 = (ans1 + f[k - 1][a[j]]) % MOD; //往上涂抹的方案数 ans2 = (ans2 + f[n - k][a[j]]) % MOD; //往下涂抹的方案数 } cout << (long long) ans1 * ans2 % MOD; return 0; }
#include#define LL long long using namespace std; int n, m; //n * n的棋盘,摆放m个国王 LL f[19][109][1099]; //f[i][j][k]:前i行摆放j个国王,第i行状态为k的合法方案数 int cnt, st[1099]; //一共有cnt种合法的状态 int c[1099]; //c[k]表示状态k有几个国王 int countBit(int k) { int res = 0; while (k) res ++, k &= k - 1; return res; } int main() { cin >> n >> m; for (int k = 0; k < 1 << n; k ++) { //列出m种合法的状态 if (!(k >> 1 & k)) { //没有相邻的国王才是合法状态 st[++ cnt] = k; c[k] = countBit(k); } } //当n = 10时,cnt只有144,所以以下代码不会超时,约等于2e7 f[0][0][0] = 1; for (int i = 1; i <= n + 1; i ++) { for (int j = 0; j <= m; j ++) { for (int l2 = 1; l2 <= cnt; l2 ++) { for (int l1 = 1; l1 <= cnt; l1 ++) { int k1 = st[l1]; //第i - 1行的状态为k1 int k2 = st[l2]; //第i行的状态为k2 if (!(k1 & k2) && !(k1 >> 1 & k2) && !(k1 << 1 & k2)) { if (j >= c[k2]) f[i][j][k2] += f[i - 1][j - c[k2]][k1]; //不必判断j >= c[k1] + c[k2],因为不合法的情况f为0,不影响结果 //但必须判断j >= c[k2],因为下标不能越界 } } } } } cout << f[n + 1][m][0]; return 0; }
预处理和每个状态兼容的其它状态
#include#define LL long long using namespace std; int n, m; //n * n的棋盘,摆放m个国王 LL f[19][109][1099]; //f[i][j][k]:前i行摆放j个国王,第i行状态为k的合法方案数 vector st; //st存放所有合法的状态 vector head[1099]; //head[k]存放所有和状态k相容的状态 int c[1099]; //c[k]表示状态k有几个国王 int countBit(int k) { int res = 0; while (k) res ++, k &= k - 1; return res; } int main() { cin >> n >> m; for (int k = 0; k < 1 << n; k ++) { //列出m种合法的状态 if (!(k >> 1 & k)) { //没有相邻的国王才是合法状态 st.push_back(k); c[k] = countBit(k); } } for (int l2 = 0; l2 < st.size(); l2 ++) { for (int l1 = 0; l1 < st.size(); l1 ++) { int k1 = st[l1]; //第i - 1行的状态为k1 int k2 = st[l2]; //第i行的状态为k2 if (!(k1 & k2) && !(k1 >> 1 & k2) && !(k1 << 1 & k2)) { head[k2].push_back(k1); } } } f[0][0][0] = 1; for (int i = 1; i <= n + 1; i ++) { for (int j = 0; j <= m; j ++) { for (int l2 = 0; l2 < st.size(); l2 ++) { int k2 = st[l2]; //第i行的状态为k2 for (int l1 = 0; l1 < head[k2].size(); l1 ++) { int k1 = head[k2][l1]; //第i - 1行的状态为k1 if (j >= c[k2]) f[i][j][k2] += f[i - 1][j - c[k2]][k1]; //不必判断j >= c[k1] + c[k2],因为不合法的情况f为0,不影响结果 //但必须判断j >= c[k2],因为下标不能越界 } } } } cout << f[n + 1][m][0]; return 0; }



