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
    
    
  • 相关阅读:
    雨课堂知识点总结(六)
    软件构造雨课堂知识点总结(五)
    软件构造雨课堂知识点总结(四)
    软件构造雨课堂知识点总结(三)
    0-N-0计数的优化写法
    Nginx TP5环境配置
    小程序跳转H5及其他页面
    mysql中varchar类型和datetime类型字段进行比较
    微信小程序开发者工具更新后报很多错误
    php后台解决跨域
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12241231.html
Copyright © 2011-2022 走看看