小国王

来源 : https://www.acwing.com/problem/content/1066/

n x n 的棋盘上放 k 个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数。

#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define pb push_back
#define PII pair<int, int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 12, M = 1 << N;
vector<int> state;
vector<int> head[M];
int cnt[M];
ll f[N][110][1 << N];
int n, m;

bool check(int x) {
    for (int i = 0; i < n; ++i) 
        if ((x >> i & 1) && (x >> i + 1 & 1)) return false;
    return true;
}

int count(int x) {
    int res = 0;
    for (int i = 0; i < n; ++i) res += x >> i & 1;
    return res;
}

int main() {
    IO;
    cin >> n >> m; 
    for (int i = 0; i < 1 << n; ++i) 
        if (check(i)) {
            state.pb(i);
            cnt[i] = count(i);  
        }

    for (int i = 0; i < state.size(); ++i)  
        for (int j = 0; j < state.size(); ++j) {
            int a = state[i], b = state[j];
            if ((a & b) == 0 && check(a | b))
            head[i].pb(j);
        }

    f[0][0][0] = 1;
    for (int i = 1; i <= n + 1; ++i)
        for (int j = 0; j <= m; ++j)
            for (int a = 0; a < state.size(); ++a)
                for (int b : head[a]) {
                    int c = cnt[state[a]];
                    if (j >= c)
                        f[i][j][a] += f[i - 1][j - c][b];
                }
    
    cout << f[n + 1][m][0] << endl;
           
    return 0;
}
    
posted @ 2021-01-25 13:55  phr2000  阅读(102)  评论(0编辑  收藏  举报