P1896 [SCOI2005]互不侵犯
阿新 • • 發佈:2021-08-10
[SCOI2005]互不侵犯
題目描述
在N×N的棋盤裡面放K個國王,使他們互不攻擊,共有多少種擺放方案。國王能攻擊到它上下左右,以及左上左下右上右下八個方向上附近的各一個格子,共8個格子。 注:資料有加強(2018/4/25)輸入輸出格式
輸入格式
只有一行,包含兩個數N,K ( 1 <=N <=9, 0 <= K <= N \* N)輸出格式
所得的方案數輸入輸出樣例
輸入樣例 #1
3 2
輸出樣例 #1
16
狀壓模板題
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; int n, k; const int N = 12; long long f[N][N * N][1 << N]; vector state, head[1 << N]; int cnt[1 << N]; bool check(int state) { for(int i = 0 ; i < n; i++) { if((state >> i & 1 ) && (state >> i + 1 & 1)) { return 0; } } return 1; } int count(int state) { int res = 0 ; for(int i = 0 ; i < n; i++) res += state >> i & 1; return res; } int main() { scanf("%d %d", &n, &k); for(int i = 0; i < 1 << n; i++) { if(check(i)) { state.push_back(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].push_back(j); } f[0][0][0] = 1; for(int i = 1; i <= n + 1; i++) { for(int j = 0 ; j <= k; j++) { for(int a = 0 ;a < state.size(); a++) { for(int p = 0 ; p < head[a].size(); p++) { int b = head[a][p]; int c = cnt[state[a]]; if(j >= c) { f[i][j][a] += f[i - 1][j - c][b]; } } } } } printf("%lld", f[n + 1][k][0]); return 0; }