AcWing 1064. 小国王

原题链接

原来蒙德里安的梦想和最短路径是两个状压的套路题型....蒟蒻落泪

考察:状压dp

思路:

       参考蒙德里安的梦想,本题如果i行的摆放只与i-1行有关.也就是说设i-1行的摆放情况为a,i行为b.要满足这些条件:a&b=0,a无连续1,b无连续1,a|b无连续1.

       预处理合法的状态.再枚举合法的可转化状态.再套模板即可

注意: 答案是long long

         需要定义三维状态f[i][j][k]分别表示第i行,第i行的状态j,放了k个国王.

 1 #include <iostream> 
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <vector>
 6 using namespace std;
 7 typedef long long ll;
 8 typedef vector<int> VI;
 9 const int N = 11;
10 int n,k,cnt[1<<N];
11 bool st[1<<N];
12 VI v[1<<N];
13 ll f[N][1<<N][N*N];
14 void inits()
15 {
16     f[0][0][0] = 1;
17     for(int i=0;i<1<<n;i++)
18     {
19         int cnt = 0;
20         for(int j=0;j<n;j++)
21         {
22             if(i>>j&1) cnt++;
23             else cnt = 0;
24             if(cnt>1) break;
25         }
26         if(cnt>1) st[i] = 0;
27         else st[i] = 1;
28     }
29     for(int i=0;i<1<<n;i++)
30       for(int j=0;j<1<<n;j++)
31             if(st[j]&&st[i]&&(i&j)==0&&st[i|j]) v[i].push_back(j);
32     for(int i=0;i<1<<n;i++)
33        for(int j=0;j<n;j++)
34          if(i>>j&1) cnt[i]++;
35 }
36 int main() 
37 {
38     ll ans = 0;
39     scanf("%d%d",&n,&k);
40     inits();
41     for(int i=1;i<=n;i++)
42       for(int j=0;j<1<<n;j++)
43         if(st[j])
44           for(int t=cnt[j];t<=k;t++)
45             for(auto it:v[j])
46                f[i][j][t] += f[i-1][it][t-cnt[j]];
47     for(int i=0;i<1<<n;i++)
48       ans+=f[n][i][k];
49     printf("%lld\n",ans);
50     return 0;
51 }

 

上一篇:PAT-1064(Complete Binary Search Tree)JAVA实现


下一篇:C - Cable master POJ - 1064