状压DP SCOI2005 互不侵犯King

P1896 [SCOI2005]互不侵犯King

题目描述

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

输入输出格式

输入格式:

 

只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

 

输出格式:

 

所得的方案数

 

输入输出样例

输入样例#1:
3 2
输出样例#1:
16


这是一个显然的问题
然而我并看不懂wxl和hzwer等神犇的高大上代码


贴代码
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int s[520];
 7 int num[520];
 8 int states;
 9 long long f[15][110][520];
10 int n,k;
11 long long ans;
12 
13 int main(){
14     scanf("%d%d",&n,&k);
15     for(int i=0;i<(1<<n);i++){
16         if(i&(i<<1)) continue;
17         int temp=i;
18         while(temp){
19             num[states]+=(temp&1);
20             temp=temp>>1;
21         }
22         s[states++]=i;
23     }
24     for(int i=0;i<states;i++)//第一行特处理 
25         if(num[i]<=k) f[1][num[i]][i]++;
26     for(int i=2;i<=n;i++)
27         for(int j=0;j<=k;j++)
28             for(int t=0;t<states;t++){
29                 if(num[t]>j) continue;
30                 for(int q=0;q<states;q++){
31                     if(num[q]>j-num[t]) continue;
32                     if(s[t]&s[q]) continue;
33                     if((s[t]<<1)&s[q]) continue;
34                     if(s[t]&(s[q]<<1)) continue;
35                     f[i][j][t]+=f[i-1][j-num[t]][q];
36                 }
37             }
38     for(int i=0;i<states;i++) ans+=f[n][k][i];
39     printf("%lld",ans);
40     return 0; 
41 }

 

posted @ 2017-05-04 18:01  zwube  阅读(164)  评论(0编辑  收藏  举报