zoukankan      html  css  js  c++  java
  • SGU 223 国王 状压DP

    在 n×的棋盘上放 kk 个国王,国王可攻击相邻的 88 个格子,求使它们无法互相攻击的方案总数。

    状压DP是一种比较暴力的DP。

    首先dp[i][j][k]表示前i行放置k个国王,且当前行状态是j的方案数。

    转移方程 dp[i][j][k] = dp[i - 1][m][k - sum[k]]

    sum[k]表示第k个合法状态的放置的国王个数。

    什么叫第k个合法状态。由于每行的放置规则是有限的,所以可以预处理出合法状态记录到sum里和一个st数组表示第i个合法状态的国王个数。

    最后只要求 1 <= i <= cnt 下dp[n][i][k] cnt是合法状态数

    ll dp[12][1 << 10 + 5][105];
    int st[1 << 10 + 5];
    int sum[1 << 10 + 5];
    
    bool check(int x, int y) {
        if ((x & y) || (x & (y << 1)) || (x & (y >> 1))) return false;
        return true;
    }
    
    int main() {
        int n = readint();
        int k = readint();
        int cnt = 0;
        for (int i = 0; i < 1 << n; i++) {
            if (!(i & (i << 1))) {
                st[++cnt] = i;
                sum[cnt] = bitcount(i);
            }
        }
        for (int i = 1; i <= cnt; i++) dp[1][i][sum[i]] = 1;
        for (int i = 2; i <= n; i++) 
            for (int j = 1; j <= cnt; j++)
                for (int m = sum[j]; m <= k; m++)
                      for (int jj = 1; jj <= cnt; jj++)
                          if (check(st[j], st[jj])) dp[i][j][m] += dp[i - 1][jj][m - sum[j]];
        ll sum = 0;
        for (int i = 1; i <= cnt; i++) sum += dp[n][i][k];  
        Put(sum);
    }
  • 相关阅读:
    Luogu P1247 取火柴游戏
    Luogu P2148 [SDOI2009]E&D
    Luogu P3305 [SDOI2013]费用流 二分 网络流
    NTT学习笔记
    Luogu P4015 运输问题
    Lucas定理学习笔记(没有ex_lucas)
    Luogu P2613 【模板】有理数取余
    欧拉定理与扩展欧拉定理学习笔记
    BSGS与exBSGS学习笔记
    Luogu P3868 [TJOI2009]猜数字
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13479468.html
Copyright © 2011-2022 走看看