[SCOI2005]互不侵犯 题解

[SCOI2005]互不侵犯 题解

题目地址:洛谷:【P1896】[SCOI2005]互不侵犯 – 洛谷、BZOJ:Problem 1087. — [SCOI2005]互不侵犯King

题目描述

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

输入输出格式

输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

输出格式:
所得的方案数

输入输出样例

输入样例#1:

3 2

输出样例#1:

16

题解

听说是状压入门?我不知道,我的第一道状压并不是这个呀。
注意到n的范围极小,意味着可以状压来表示状态,但是状态数量很多,不能全搜一遍,考虑动态规划,只状压一行的状态。dp[i][S][j]表示第i行,状态为S且用去了j个国王的方案数,枚举上一行的状态转移过来即可。
判断是否冲突可以用左移一位、右移一位和原来的状态值去做与运算,若得到的结果非0,说明有冲突。

代码

// Code by KSkun, 2018/5
#include <cstdio>
#include <cctype>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1;
    register char c = fgc();
    while(!isdigit(c)) {
        if(c == '-') neg = -1;
        c = fgc();
    }
    while(isdigit(c)) {
        res = (res << 1) + (res << 3) + c - '0';
        c = fgc();
    }
    return res * neg;
}

int n, k, cnt[1 << 9];
LL dp[10][1 << 9][85];
bool can[1 << 9];

int main() {
    n = readint(); k = readint();
    for(int i = 1; i < 1 << n; i++) {
        cnt[i] = cnt[i >> 1] + (i & 1);
    }
    for(int i = 0; i < 1 << n; i++) {
        if((i & (i << 1)) || (i & (i >> 1))) continue;
        can[i] = true; dp[1][i][cnt[i]] = 1;
    }
    for(int i = 2; i <= n; i++) {
        for(int s = 0; s < 1 << n; s++) {
            if(!can[s]) continue;
            for(int t = 0; t < 1 << n; t++) {
                if(!can[t]) continue;
                if((s & t) || (s & (t >> 1)) || (s & (t << 1))) continue;
                for(int j = cnt[t]; j <= k; j++) {
                    dp[i][s][j + cnt[s]] += dp[i - 1][t][j];
                }
            }
        }
    }
    LL ans = 0;
    for(int i = 0; i < 1 << n; i++) {
        ans += dp[n][i][k];
    }
    printf("%lld", ans);
    return 0;
}


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据