• 状压DP SGU 223 Little Kings


    题目传送门

      1 /*
      2     题意:n*n的矩阵,放置k个king,要求king互相不能攻击,即一个king的8个方向都没有另外的king,求方案个数
      3     状态压缩DP:dp[i][num[j]][s] 代表在第i行,放置num[j]个king,其状态为s时的方案数
      4                 首先对state进行筛选,即一行king左右相邻没有另外的king,确定tot
      5                 接着对第一行进行处理,对2~n行DP递推,同样要满足各种条件限制,num个数和不超过k,s1,s2状态也要ok
      6                 最后累加放置k个king时的方案数
      7     详细解释:http://blog.csdn.net/roney_win/article/details/9617081
      8 */
      9 #include <cstdio>
     10 #include <iostream>
     11 #include <algorithm>
     12 #include <cstring>
     13 #include <cmath>
     14 #include <map>
     15 #include <set>
     16 #include <string>
     17 using namespace std;
     18 
     19 const int MAXN = 15;
     20 const int INF = 0x3f3f3f3f;
     21 long long dp[15][110][150];
     22 int st[150];
     23 int num[150];
     24 
     25 bool ok(int x)
     26 {
     27     if ((x & (x << 1)) == 0)    return true;
     28     else    return false;
     29 }
     30 
     31 int init_state(int n, int k)
     32 {
     33     int tot = 1 << n;
     34     int cnt = 0;
     35     for (int i=0; i<tot; ++i)
     36     {
     37         if (ok (i))
     38         {
     39             num[cnt] = 0;
     40             int t = i;
     41             while (t)
     42             {
     43                 num[cnt] += (t & 1);
     44                 t >>= 1;
     45             }
     46             st[cnt++] = i;
     47         }
     48     }
     49 
     50     return cnt;
     51 }
     52 
     53 int main(void)        //SGU 223 Little Kings
     54 {
     55     #ifndef ONLINE_JUDGE
     56     freopen ("E.in", "r", stdin);
     57     #endif
     58 
     59     int n, k;
     60     while (~scanf ("%d%d", &n, &k))
     61     {
     62         int tot = init_state (n, k);
     63         memset (dp, 0, sizeof (dp));
     64 
     65         for (int s=0; s<tot; ++s)
     66         {
     67             if (num[s] <= k)
     68             {
     69                 dp[1][num[s]][s]++;
     70             }
     71         }
     72 
     73         for (int i=1; i<=n-1; ++i)
     74         {
     75             for (int j=0; j<=k; ++j)
     76             {
     77                 for (int s1=0; s1<tot; ++s1)
     78                 {
     79                     if (num[s1] <= j)
     80                     {
     81                         int res = j - num[s1];
     82                         for (int s2=0; s2<tot; ++s2)
     83                         {
     84                             if (num[s2] <= res)
     85                             {
     86                                 if ((st[s1] & st[s2]) == 0)
     87                                 {
     88                                     if (((st[s1] & (st[s2] << 1)) == 0) && ((st[s1] & (st[s2] >> 1)) == 0))
     89                                     {
     90                                         dp[i+1][j][s1] += dp[i][res][s2];
     91                                     }
     92                                 }
     93                             }
     94                         }
     95                     }
     96                 }
     97             }
     98         }
     99 
    100         long long ans = 0;
    101         for (int s=0; s<tot; ++s)
    102         {
    103             if (num[s] <= k)
    104             {
    105                 ans += dp[n][k][s];
    106             }
    107         }
    108 
    109         printf ("%I64d
    ", ans);
    110 
    111     }
    112 
    113     return 0;
    114 }
    115 
    116 
    117 /*
    118 Test #1
    119 */
    编译人生,运行世界!
  • 相关阅读:
    Python中CreateCompatibleDC和CreateBitmap造成的内存泄漏
    POJ 2420 模拟退火
    LR(1)分析表-语法树-四元式
    C语言文法
    计蒜客 18018 热爱工作的蒜蒜 最短路+dp
    HDU 5988 最小费用流
    POJ 1808 平方剩余
    POJ 2115 单变元模线性方程
    计蒜客 17414 Exponial 指数降幂公式
    计蒜客 17412 Card Hand Sorting 最长公共子序列
  • 原文地址:https://www.cnblogs.com/Running-Time/p/4368526.html
Copyright © 2020-2023  润新知