[AcWing 1064] 小国王

image


点击查看代码
#include<iostream>
#include<cstring>
#include<vector>

using namespace std;

typedef long long LL;

const int N = 12, M = 1 << 10, K = 110;

int n, m;
vector<int> state;
int cnt[M];
vector<int> head[M];
LL f[N][K][M];

bool check(int x)
{
    for (int i = 0; i < n; i ++)
        if ((x >> i & 1) && ((x >> i + 1 & 1)))
            return false;
    return true;
}

int count(int x)
{
    int res = 0;
    for (int i = 0; i < n; i ++)
        res += x >> i & 1;
    return res;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < 1 << n; i ++)
        if (check(i)) {
            state.push_back(i);
            cnt[i] = count(i);
        }
    for (auto a : state)
        for (auto b : state) {
            if ((a & b) == 0 && check(a | b))
                head[a].push_back(b);
        }   
    f[0][0][0] = 1;
    for (int i = 1; i <= n + 1; i ++)
        for (int j = 0; j <= m; j ++)
            for (auto a : state)
                for (auto b : head[a]) {
                    int c = cnt[a];
                    if (j >= c)
                        f[i][j][a] += f[i - 1][j - c][b];
                }
    cout << f[n + 1][m][0] << endl;
    return 0;
}

  1. 状态表示
    f[i][j][s] 表示所有只摆前 i 行,已经摆了 j 个国王,并且第 i 行的状态是 s 的所有方案的个数
  2. 状态计算
    合法的状态才能转移,第 i 行只与第 i1 行有关,合法的状态:
    设第 i 行的状态为 a,第 i1 行的状态为 b
    ① 不能有两个国王在同一列,即 a & b==0
    ② 不能有两个国王处在相邻的列,即 a | b 不能有两个连续的 1
    满足上述条件的情况下:
    f[i][j][a] += f[i1][jcount(a)][b] (count(a) 表示 a 的二进制表示中 1 的个数)
posted @   wKingYu  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
欢迎阅读『[AcWing 1064] 小国王』
点击右上角即可分享
微信分享提示