zoukankan      html  css  js  c++  java
  • 洛谷 P1896 [SCOI2005]互不侵犯

    题目描述

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

    注:数据有加强(2018/4/25)

    输入格式

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

    输出格式

    所得的方案数

    输入输出样例

    输入 #1
    3 2
    
    输出 #1
    16

    思路:也是状压dp,每一行的状态不受行的限制,预处理出行的状态s[i],每一个状态安放了几个棋子c[i],dp[i][j][k]表示前i行,第i行状态是j时,已经放了k个棋子的种类数,dp[i][j][k]=sum(dp[i-1][m][k-c[i]]),s[j]&s[m] == 0, s[j]&s[m]>>1 == 0, s[j]&s[m]<<1 == 0,满足三个条件,说明第i-1行的状态不冲突
    typedef long long LL;
    
    const int maxm = (1<<10) + 5;
    
    int s[maxm], c[maxm]; 
    LL dp[10][maxm][85];
    int n, k, cnt;
    
    void dfs(int j, int state, int num) {
        if(j >= n) return;
        c[cnt] = num;
        s[cnt++] = state;
        for(int k = j+2; k < n; ++k) {
            if(!((1<<(k-1))&state)) dfs(k, state|(1<<k), num+1);
        }
    }
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        cin >> n >> k; 
        for(int i = 0; i < n; ++i)
            dfs(i, 1<<i, 1);
        cnt++;
        for(int i = 0; i < cnt; ++i)
            dp[0][i][c[i]] = 1;
        for(int i = 1; i < n; ++i) {
            for(int j = 0; j < cnt; ++j) {
                for(int m = 0; m < cnt; ++m) {
                    if(((s[j]&s[m]) || (s[j] & (s[m]>>1)) || (s[j] & (s[m]<<1))) == 0)
                        for(int x = k; x >= c[j]; x--)
                            dp[i][j][x] += dp[i-1][m][x-c[j]];
                }
            }
        }
        LL ans = 0;
        for(int i = 0; i < cnt; ++i)
            ans += dp[n-1][i][k];
        cout << ans << "
    ";
        return 0;
    }
    View Code
    
    
  • 相关阅读:
    win32: 静态控件(Static)
    malloc() 和 calloc()有啥区别
    win32: WM_PAINT 实现双缓冲缓图
    char 与 unsigned char的本质区别
    iconv: iconv_open(pToCharset, pFromCharset); 的附加参数//IGNORE
    c语言: 生成随机数
    深圳市住房公积金管理中心
    利用latex制作个人简历
    分布式系统概念与设计中文版(第三版)
    数据结构-红黑树
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12241231.html
Copyright © 2011-2022 走看看