C++之路进阶——codevs2451(互不侵犯)

2451 互不侵犯

 

2005年省队选拔赛四川

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

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

输入描述 Input Description

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

输出描述 Output Description

      方案数。

样例输入 Sample Input

3 2

样例输出 Sample Output

16

数据范围及提示 Data Size & Hint

1 <=N <=9,  0 <= K <= N * N

题解:

   用二进制表示状态,进行dp。

代码:

  

 1 #include<cstdio>
 2 #include<iostream>
 3 #define maxn 600
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 int n,m,b1[maxn],b2[maxn][maxn],sum[maxn];
 9 long long f[10][maxn][maxn];
10 
11 int main()
12   {
13       scanf("%d%d",&n,&m);
14       int s=(1<<n)-1;
15       for (int i=0;i<=s;i++)
16          if ((i&(i>>1))==0)
17             {
18                 b1[i]=1;
19                 int q=0;
20                 for (int j=i;j;j=j>>1)
21                     if (j&1)
22                        q++;
23                 sum[i]=q;       
24             }
25       for (int i=0;i<=s;i++)
26          if (b1[i])
27                  for (int j=0;j<=s;j++)
28                    if (b1[j]&&(i&j)==0&&((i<<1)&j)==0&&((i>>1)&j)==0)
29                             b2[i][j]=1;
30     for (int i=0;i<=s;i++)
31         f[1][sum[i]][i]=1;
32     for (int i=1;i<n;i++)        
33         for (int j=0;j<=s;j++)
34             if (b1[j])
35                 for (int k=0;k<=s;k++)
36                    if (b1[k]&&b2[j][k])
37                       {
38                            for (int q=sum[j];q+sum[k]<=m;q++)
39                               f[i+1][sum[k]+q][k]+=f[i][q][j];
40                        }
41     long long ans=0;                    
42     for (int i=0;i<=s;i++)                   
43        ans+=f[n][m][i];
44     printf("%lld
",ans);   
45       return 0;    
46   }
原文地址:https://www.cnblogs.com/grhyxzc/p/5202615.html