洛谷 P1896 [SCOI2005]互不侵犯
作者:互联网
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
输入输出样例
输入 #13 2输出 #1
16
思路:也是状压dp,每一行的状态不受行的限制,预处理出行的状态s[i],每一个状态安放了几个棋子c[i],dp[i][j][k]表示前i行,第i行状态是j时,已经放了k个棋子的种类数,dp[i][j][k]=sum(dp[i-1][m][k-c[i]]),s[j]&s[m] == 0, s[j]&s[m]>>1 == 0, s[j]&s[m]<<1 == 0,满足三个条件,说明第i-1行的状态不冲突
typedef long long LL; const int maxm = (1<<10) + 5; int s[maxm], c[maxm]; LL dp[10][maxm][85]; int n, k, cnt; void dfs(int j, int state, int num) { if(j >= n) return; c[cnt] = num; s[cnt++] = state; for(int k = j+2; k < n; ++k) { if(!((1<<(k-1))&state)) dfs(k, state|(1<<k), num+1); } } int main() { ios::sync_with_stdio(false), cin.tie(0); cin >> n >> k; for(int i = 0; i < n; ++i) dfs(i, 1<<i, 1); cnt++; for(int i = 0; i < cnt; ++i) dp[0][i][c[i]] = 1; for(int i = 1; i < n; ++i) { for(int j = 0; j < cnt; ++j) { for(int m = 0; m < cnt; ++m) { if(((s[j]&s[m]) || (s[j] & (s[m]>>1)) || (s[j] & (s[m]<<1))) == 0) for(int x = k; x >= c[j]; x--) dp[i][j][x] += dp[i-1][m][x-c[j]]; } } } LL ans = 0; for(int i = 0; i < cnt; ++i) ans += dp[n-1][i][k]; cout << ans << "\n"; return 0; }View Code
标签:cnt,洛谷,++,P1896,long,int,ans,SCOI2005,dp 来源: https://www.cnblogs.com/GRedComeT/p/12241231.html