• 互不侵犯【状压】


    互不侵犯【状压】

    description

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

    (1 <= N <= 9, 0 <= K <= N x N)

    input

    只有一行,包含两个数 n, k。

    output

    所得的方案数。

    Sample

    3 2
    
    16
    

    题解

    大家都做过玉米地吧,这其实和那道题很像,只是玉米地是上下左右冲突,这个多了个角上也冲突,那就再加两个if判断角上冲突的情况

    具体流程详见注释

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define int long long
    using namespace std;
    int dp[10][1<<10][100];//dp[i][j][k]表示第i行摆放的国王状态为j,总共摆放k个国王的方案数
    int state[1<<10], num[1<<10];//预处理每行所有合法的状态和他们包含1的个数
    int n, cnt, tot, ans;//tot为每行合法状态总数
    int lowbit(int x){return x & -x;}
    int getnum(int x){//求状态x中1的个数
        int ans = 0;
        for(int i=1; i<=n; i++) if(x & (1<<(i-1))) ans ++;
        return ans;
    }
    signed main(){
        scanf("%lld%lld", &n ,&cnt);
        for(int i=0; i<(1<<n); i++) if(!(i & (i<<1))) state[++tot] = i, num[tot] = getnum(i);//预处理合法状态
        for(int i=1; i<=tot; i++) dp[1][i][num[i]] = 1;//第一行特殊处理
        for(int i=2; i<=n; i++){
            for(int j=1; j<=tot; j++){//枚举当前行的状态
                for(int k=1; k<=tot; k++){//枚举上一行的状态
                    if(state[j] & state[k]) continue;//上下相邻,相互攻击
                    if(state[j] & (state[k]<<1)) continue;//攻击左上
                    if(state[j] & (state[k]>>1)) continue;//攻击右上
                    for(int now=cnt; now>=num[j]; now--){//状态合法,此时我们枚举当前棋盘上已经放的国王数量
                        dp[i][j][now] += dp[i-1][k][now - num[j]];
                    }
                }
            }
        }
        for(int i=1; i<=tot; i++) ans += dp[n][i][cnt]; //枚举最后一行的方案,求和方案数
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    青城的另一个一夜/情
    SystemProperties.get/set property_get/set
    锁——Java同步的基本思想
    CMUSphinx Learn
    猜数字
    我的音乐我的电影
    动态规划_钢条切割问题
    directdraw显示yuv420(YV12)
    Redis 命令参考
    HDU 3078 LCA转RMQ
  • 原文地址:https://www.cnblogs.com/hzoi-poozhai/p/12711644.html
Copyright © 2020-2023  润新知