BZOJ 1087 [SCOI2005]互不侵犯King

暴力状压dp。。。

好久不写状压dp,先水一个~

 

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <algorithm>
 6 
 7 #define N 1000
 8 
 9 using namespace std;
10 
11 int num,n,m;
12 int zt[N],gs[N];
13 long long dp[11][1<<11][90];
14 bool map[N][N];
15 
16 inline bool check(int x,int y)
17 {
18     if(x&(y<<1)) return false;
19     if(x&(y>>1)) return false;
20     if(x&y) return false;
21     return true;
22 }
23 
24 inline bool judge(int x)
25 {
26     if(x&(x<<1)) return false;
27     if(x&(x>>1)) return false;
28     return true;
29 }
30 
31 inline int getnum(int x)
32 {
33     int res=0;
34     while(x)
35     {
36         if(x&1) res++;
37         x>>=1;
38     }
39     return res;
40 }
41 
42 inline void prev()
43 {
44     int sum=(1<<n)-1;
45     for(int i=0;i<=sum;i++)
46         if(judge(i))
47         {
48             zt[++num]=i;
49             gs[num]=getnum(i);
50         }
51     for(int i=1;i<=num;i++)
52         for(int j=i;j<=num;j++)    
53             if(check(zt[i],zt[j]))
54                 map[j][i]=map[i][j]=true;
55 }
56 
57 inline void go()
58 {
59     dp[0][1][0]=1LL;
60     for(int i=0;i<n;i++)
61         for(int j=1;j<=num;j++)
62             for(int k=0;k<=m;k++)
63                 if(dp[i][j][k])
64                     for(int p=1;p<=num;p++)
65                         if(map[j][p]&&k+gs[p]<=m)
66                             dp[i+1][p][k+gs[p]]+=dp[i][j][k];
67     long long sum=0;
68     for(int i=1;i<=num;i++)
69         sum+=dp[n][i][m];
70     printf("%lld\n",sum);
71 }
72 
73 int main()
74 {
75     scanf("%d%d",&n,&m);
76     prev();
77     go();
78     return 0;
79 }

 

 

posted @ 2013-01-18 22:45  proverbs  阅读(886)  评论(0编辑  收藏  举报