SGU 223 Little Kings

每行摆棋子状态位压缩,对能够相邻的行链表建图,dp[n行][状态1024][还剩下没放的棋子数k],最后把dp[n][all(合法)][0]相加。

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 const int maxn = 1033;
 5 int fst[1033], nex[maxn * maxn], v[maxn * maxn];
 6 int wnum;
 7 void Add(int a, int b)
 8 {
 9     nex[wnum] = fst[a];
10     fst[a] = wnum;
11     v[wnum] = b;
12     wnum ++;
13 }
14 
15 bool OK(int a)
16 {
17     if((a & 1) && (a & 2)) return false;
18     int i;
19     for(i = 1; i < 10; i ++)
20         if((a >> i & 1) && ((a >> (i + 1) & 1) || (a >> (i - 1) & 1)))
21             return false;
22     if((a >> i & 1) && (a >> (i - 1) & 1))
23         return false;
24     return true;
25 }
26 bool OK(int a, int b)
27 {
28     if((a & 1) && ((b & 1) || (b & 2)))
29         return false;
30     int i;
31     for(i = 1; i < 10; i ++)
32     {
33         if((a >> i & 1) && ((b >> (i - 1) & 1) || (b >> i & 1) || (b >> (i + 1) & 1)))
34             return false;
35     }
36     if((a >> i & 1) && ((b >> (i - 1) & 1) || (b >> i & 1)))
37         return false;
38     return true;
39 }
40 
41 bool ok[maxn];
42 bool ook[maxn][maxn];
43 void Build()
44 {
45     for(int i = 0; i < maxn; i ++) ok[i] = OK(i);
46     for(int i = 0; i < maxn; i ++)
47         for(int j = 0; j < maxn; j ++) ook[i][j] = ok[i] && ok[j] && OK(i, j);
48     for(int i = maxn - 1; i >= 0; i --)
49     {
50         for(int j = maxn - 1; j >= 0; j --)
51         {
52             if(ok[i] && ok[j] && ook[i][j])
53                 Add(i, j);
54         }
55     }
56 }
57 int n, k;
58 __int64 dp[11][maxn][111];
59 int COUNT(int x)
60 {
61     int cnt = 0;
62     while(x) cnt ++, x &= x - 1;
63     return cnt;
64 }
65 int main()
66 {
67     memset(fst, -1, sizeof(fst));
68     wnum = 0;
69     Build();
70     while(scanf("%d%d", &n, &k) != EOF)
71     {
72         memset(dp, 0, sizeof(dp));
73         int M = 1 << n;
74         for(int i = 0; i < M; i ++)
75             if(COUNT(i) <= k)
76                 dp[0][i][k - COUNT(i)] = ok[i];
77         for(int i = 1; i < n; i ++)
78         {
79             for(int j = 0; j < M; j ++)
80             {
81                 for(int u = fst[j]; u != -1 && v[u] < M; u = nex[u])
82                 {
83                     for(int K = COUNT(v[u]); K <= k; K ++)
84                         dp[i][v[u]][K - COUNT(v[u])] += dp[i - 1][j][K];
85                 }
86             }
87         }
88         __int64 ans = 0;
89         for(int i = 0; i < M; i ++)
90             ans += dp[n - 1][i][0];
91         printf("%I64d\n", ans);
92     }
93     return 0;
94 }

 

posted @ 2013-09-24 20:33  CSGrandeur  阅读(339)  评论(0编辑  收藏  举报