zoukankan      html  css  js  c++  java
  • bzoj1087: [SCOI2005]互不侵犯King 状压dp

    Description

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

    Input

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

    Output

      方案数。

    题解

    玉米田(轻击有惊喜)的解法一样。预处理一行所有合法情况。由于是四周的八个格子都不能有国王,在判断时多一个左移、右移,然后dp扫一遍

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int mod=1e9;
    const int maxn=(1<<9)+10;
    typedef long long ll;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,k;
    int is[maxn];
    ll f[10][maxn][90];
    int main(){
        n=read();k=read();
        for(int i=0;i<(1<<n);i++){
            is[i]=((i&(i<<1))==0)&&((i&(i<<1))==0);
            if(is[i]){
                int num=__builtin_popcount(i);
                if(num>k)continue;
                f[1][i][num]=1;
            }
        }
        for(int i=2;i<=n;i++) for(int j=0;j<(1<<n);j++)
            if(is[j]){
                int num1=__builtin_popcount(j);
                for(int p=0;p<(1<<n);p++) if(((p&j)==0)&&((p&(j<<1))==0)&&((p&(j>>1))==0))
                    for(int q=0;q<=k-num1;q++) f[i][j][q+num1]+=f[i-1][p][q]; 
            }
        ll ans=0;
        for(int i=1;i<=n;i++) for(int j=1;j<(1<<n);j++)
            if(is[j])ans+=f[i][j][k];
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    06.数组模拟栈-简易计算器
    05.单向环形链表应用 -- 约瑟夫环
    02.数组模拟环形队列
    01.稀疏矩阵与二维数组相互转化
    大数字相乘
    13.打包发布
    悦苗园公益活动
    程序猿打招自己的电子图书馆
    【技能】提高网站可用性
    【微信技能】如何通过微信号知道对方微信的二维码
  • 原文地址:https://www.cnblogs.com/Nan-Cheng/p/9741583.html
Copyright © 2011-2022 走看看