Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
状压DP入门题
f[i][j][k]表示放完i行,第i行状态为j,i行放了k个
f[i][j][k]表示放完i行,第i行状态为j,i行放了k个
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define LL long long 5 using namespace std; 6 LL state[1026],num[1026]; 7 LL f[10][1024][1024]; 8 LL N,K,m; 9 void Deal() 10 { 11 for (LL i=0;i<=(1<<N)-1;++i) 12 { 13 LL x=i,pre=-1,cnt=0;; 14 for (LL j=1;j<=9;++j) 15 { 16 if (x&1==pre) break; 17 if (x&1) cnt++; 18 pre=x&1; 19 x>>=1; 20 } 21 if (x==0 && cnt<=K) 22 state[++m]=i,num[m]=cnt; 23 } 24 } 25 26 bool check(LL x,LL y) 27 { 28 if ((state[x]&state[y])!=0) return false; 29 if (((state[x]<<1)&state[y])!=0) return false; 30 if (((state[y]<<1)&state[x])!=0) return false; 31 return true; 32 } 33 34 int main() 35 { 36 scanf("%lld%lld",&N,&K); 37 Deal();//预处理每一行的可能情况 38 for (LL i=1;i<=m;++i) f[1][i][num[i]]=1; 39 for (LL i=2;i<=N;++i) 40 for (LL j=1;j<=m;++j)//当前行状态 41 for (LL k=1;k<=m;++k) 42 for (LL l=num[j];l<=K;++l) 43 if (check(j,k)) 44 f[i][j][l]+=f[i-1][k][l-num[j]]; 45 LL ans=0; 46 for (LL i=1;i<=m;++i) 47 ans+=f[N][i][K]; 48 printf("%lld",ans); 49 }