[SCOI2005]互不侵犯(状压Dp)

Posted cjgjh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SCOI2005]互不侵犯(状压Dp)相关的知识,希望对你有一定的参考价值。

题目

原题

Solution

看到数据范围就可以想到状压,然后你就可以直接转移就好了?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
using namespace std;
inline int gi(){
    int sum=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
inline ll gl(){
    ll sum=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
int have(int s){
    int ans=0;
    while(s){
        if(s&1)ans++;s>>=1;
    }
    return ans;
}
int n,siz[2010],gs[2010],cnt;
ll dp[12][2010][101];
void dfs(int i,int s,int sum){
    if(i>=n){
        siz[++cnt]=s;
        gs[cnt]=sum;
        return;
    }
    dfs(i+1,s,sum);
    dfs(i+2,s+(1<<i),sum+1);
}
int main(){
    int i,j,k,m;
    n=gi();k=gi();
    dfs(0,0,0);
    //设dp[i][j][k]表示第i行的放置方案为j,总共放了k个的方案总数.
    //dp[i][j][k]+=dp[i-1][m][k-have(j)];
    for(i=1;i<=cnt;i++)
        dp[1][i][gs[i]]=1;
    for(i=2;i<=n;i++)
        for(j=1;j<=cnt;j++)
            for(int kk=1;kk<=cnt;kk++){
                if(siz[j]&siz[kk])continue;
                if((siz[j]<<1)&siz[kk])continue;
                if(siz[j]&(siz[kk]<<1))continue;
                for(int jj=k;jj>=gs[j];jj--)
                    dp[i][j][jj]+=dp[i-1][kk][jj-gs[j]];
            }
    ll ans=0;
    for(j=1;j<=cnt;j++)
        ans+=dp[n][j][k];
    printf("%lld
",ans);
    return 0;
}

以上是关于[SCOI2005]互不侵犯(状压Dp)的主要内容,如果未能解决你的问题,请参考以下文章

题解[SCOI2005] 互不侵犯 (状压DP)

[SCOI2005]互不侵犯(状压Dp)

BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

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

[Bzoj1083][SCOI2005]互不侵犯king(状压dp)

[状压DP]SCOI2005 互不侵犯King