zoukankan      html  css  js  c++  java
  • [Bzoj1087][SCOI2005]互不侵犯King(状压dp)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1087

    还不错的状态压缩题目,把国王的位置看成1,其余位置看成0,则n行每行的可能出现的状态为1<<n,如果同时考虑n行的状态就为1<<(n*n),必不可能。

    所以先预处理出每行所有的合法状态,及没有相邻的1出现,并处理出每个状态的1的个数。

    定义状态dp[i][j][k]表示1-i行中第i行为j状态,1-i行中有k个国王时的方案数。

    则转移为$dp[i][j][k]=sum dp[i-1][{j}'][{k}'],{j}'和{k}'$为可以转移的合法状态。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 ll dp[15][1100][110];
     5 ll st[1100], kth[1100];
     6 int main() {
     7     int n, k;
     8     scanf("%d%d", &n, &k);
     9         int len = 0;
    10         for (int i = 0; i < (1 << n); i++) {
    11             if (!((i << 1)&i)) {
    12                 st[++len] = i;
    13                 kth[len] = 0;
    14                 int w = i;
    15                 while (w) {
    16                     kth[len] += w % 2;
    17                     w /= 2;
    18                 }
    19             }
    20         }
    21         for (int i = 1; i <= len; i++) {
    22             if (kth[i] <= k)
    23                 dp[1][i][kth[i]] = 1;
    24         }
    25         for (int i = 2; i <= n; i++) {
    26             for (int j = 1; j <= len; j++) {
    27                 for (int p = 1; p <= len; p++) {
    28                     if ((st[j] & st[p]))
    29                         continue;
    30                     if ((st[j] & (st[p] << 1)))
    31                         continue;
    32                     if (((st[j] << 1) & st[p]))
    33                         continue;
    34                     for (int kk = 1; kk <= k; kk++) {
    35                         if (kth[j] + kk <= k) {
    36                             dp[i][j][kth[j] + kk] += dp[i - 1][p][kk];
    37                         }
    38                     }
    39 
    40                 }
    41             }
    42         }
    43         ll ans = 0;
    44         for (int i = 1; i <= n; i++) {
    45             for (int j = 1; j <= len; j++) {
    46                 ans += dp[i][j][k];
    47             }
    48         }
    49         printf("%lld
    ", ans);
    50         return 0;
    51 }
  • 相关阅读:
    stc单品机的命名规则
    代码导入单片机运行
    openlayers tips
    LeetCode 766. Toeplitz Matrix
    【题集】二叉树的遍历各类题型汇总
    LeetCode 821. Shortest Distance to a Character
    关于C++中vector<vector<int> >的使用
    POJ
    LeetCode#155 Min Stack
    LeetCode#160 Intersection of Two Linked Lists
  • 原文地址:https://www.cnblogs.com/sainsist/p/11118196.html
Copyright © 2011-2022 走看看