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 }

 

你可能感兴趣的:(it)