在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。ios
注:数据有增强(2018/4/25)git
输入格式:函数
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)spa
输出格式:code
所得的方案数get
输入样例#1:it
3 2
输出样例#1:io
16
由\(n \le 9\)能够看粗应该是个状压DPclass
因此就能够高高兴兴个设状态了stream
用\(f[i][j][k]\)表示前\(i\) 行 最后一行状态为\(j\)放\(k\)个的方案数
须要两个函数判断状态合不合法还有放置的个数
inline int bitcnt(int x,int ans=0){ for(;x;x&=(x-1),++ans); return ans; }
用来判断二进制中有几个一(\(x\&=x-1\)是否是很熟悉没错就是今年初赛题)
inline bool pd(int x){ return (((x<<1)&x)||((x>>1)&x)); }
这个用来判断一个数合不合法(一个1左右不能有另外一个1)
而后就能够列状态转移方程了
\(\displaystyle f[i][j][k]=\sum_{l与j合法}f[i-1][l][k-bitcnt(k)]\)
#include<iostream> #include<cstdio> using namespace std; #define int long long int mian(){ int s=0,f=1;char ch; while(!isdigit(ch=getchar()))(ch=='-')&&(f=-1); for(s=ch-'0';isdigit(ch=getchar());s=s*10+ch-'0'); return s*f; } /* 子供の时の梦は言えますか その梦すら 沟に 舍てたのは */ int f[10][(1<<10)+1][100]; int n,m; inline int bitcnt(int x,int ans=0){ for(;x;x&=(x-1),++ans); return ans; } inline bool pd(int x){ return (((x<<1)&x)||((x>>1)&x)); } signed main(){ n=mian(),m=mian(); const int U = (1<<n)-1; f[0][0][0]=1; for(int i=1;i<=n;++i){ for(int k=0;k<=U;++k){ if(pd(k))continue; for(int l=0;l<=U;++l){ if(pd(l))continue; if(l&k)continue; if((l>>1)&k)continue; if((l<<1)&k)continue; // cout<<k<<' '<<l<<endl; int c=bitcnt(k); for(int o=c;o<=m;++o) f[i][k][o]+=f[i-1][l][o-c]; } } } int ans=0; for(int i=0;i<=U;++i)ans+=f[n][i][m]; cout<<ans<<endl; return 0; }