【洛谷 1896】互不侵犯_new
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
输入输出样例
输入 #1
3 2
输出 #1
16
题解:更新版本的嘻嘻。
#include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; typedef long long ll; int n,k; ll dp[13][15002][81],sum,ans,cnt; ll st[787878],ki[78787]; void init(){ scanf("%d %d",&n,&k); int op=(1<<n); for(int i=0;i<op;i++){ if(!((i<<1)&i)){ st[++cnt]=i; int mt=i; while(mt){ ki[cnt]+=mt%2; mt>>=1; } } } } void work(){ for(int i=1;i<=cnt;i++) if(ki[i]<=k) dp[1][i][ki[i]]=1; for(int i=2;i<=n;i++){//枚举行数 for(int j=1;j<=cnt;j++){//枚举状态 for(int p=1;p<=cnt;p++){//枚举上一行状态 if((st[j] & st[p])||((st[j]<<1) & st[p])||(st[j] & (st[p]<<1))) continue; for(int s=1;s<=k;s++){ if(ki[j]+s>k) continue; dp[i][j][ki[j]+s]+=dp[i-1][p][s]; } } } } for(int i=1;i<=n;i++) for(int j=1;j<=cnt;j++) ans+=dp[i][j][k]; cout<<ans; } int main(){ //freopen("1896.in","r",stdin); //freopen("1896.out","w",stdout); init(); work(); return 0; }