• 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
    ", ans);
    92     }
    93     return 0;
    94 }
  • 相关阅读:
    同余 扩展欧几里得
    185. [USACO Oct08] 挖水井
    Dijkstra算法
    Floyed算法
    codves——1079 回家
    codves——1021 玛丽卡
    codves——5960 信使
    计算几何基础
    【正睿oi省选十连测】第一场
    [APIO2012]守卫
  • 原文地址:https://www.cnblogs.com/CSGrandeur/p/3337605.html
Copyright © 2020-2023  润新知