• BZOJ 1087 [SCOI2005]互不侵犯King(状压DP)


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

    思路:状压dp,dp[i][j][k]为前i行放了j个,第i行状态为k

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 998244353;
    const int maxn = 2e6+100;
    const int maxm = 2e6+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    ll dp[20][200][2000];
    int n, k;
    int num[2000];
    int ys[2000];
    
    int main(){
        mem(dp, 0);
        mem(ys, 0);
        scanf("%d %d", &n, &k);
        for(int i = 0; i < (1<<n); i++){
            int p = i;
            int cnt = 0;
            while(p){
                if(p&1)cnt++;
                p>>=1;
            }
            num[i]=cnt;
        }
        for(int i = 0; i < (1<<n); i++){
            if(((i<<1)&i) ||((i>>1)&i)){
                continue;
            }
            ys[i] = 1;
            dp[1][num[i]][i]=1;
        }
        for(int i = 2; i <= n; i++){
            for(int j = 0; j <= k; j++){
                for(int p = 0; p < (1<<n); p++){//now
                    if(!ys[p])continue;
                    if(num[p]>j)continue;
                    for(int x = 0; x < (1<<n); x++){//last status from i-1
                        if(!ys[x])continue;
                        if((p&x)||((p<<1)&x)||(p>>1)&x)continue;
                        dp[i][j][p] += dp[i-1][j-num[p]][x];
    
                    }
                }
            }
        }
        ll ans = 0;
        for(int i = 0; i < (1<<n); i++){
            ans += dp[n][k][i];
        }
        printf("%lld", ans);
        return 0;
    
    }
  • 相关阅读:
    wordpress升级需设置ftp的解决方法
    用命令创建MySQL数据库
    MySQL创建用户与授权
    MySQL基本命令和常用数据库对象
    转换说明符和转换说明修饰符
    html-webpack-plugin
    数据库-之MySQL的dos命令
    浅谈Java拆箱、装箱
    Java基础问题10问
    Java单例类
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/9832606.html
Copyright © 2020-2023  润新知