牧场的安排
#include <bits/stdc++.h>
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 <bits/stdc++.h>
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 <bits/stdc++.h>
#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 <bits/stdc++.h>
#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 <int> st; //st存放所有合法的状态
vector <int> 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;
}