Luogu P1896 [SCOI2005]互不侵犯

Posted mogeko

tags:

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

gate

第二道状压dp...

预处理每种状态j所含1的个数为sum[j]

f[i][j][l]代表第i行,状态为j,当前共有l个国王

枚举本层状态j,上一层状态k,判断八方向是否有相邻:k&j||(k<<1)&j||(k>>1)&j

枚举国王数l,则有f[i][j][l] += f[i-1][k][l-sum[j]]

最后统计f[n][ ][m]即为答案

代码如下

技术图片
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;

const int mod = 1e9;

int n,m;
long long ans;
int a[10],sum[1<<9+5],g[1<<9+5];
long long f[10][1<<9+5][100];

int main() 
    scanf("%d%d",&n,&m);
    
    for(int i = 0; i < (1<<n); i++) 
        g[i] = (!((i<<1)&i) && !((i>>1)&i));
        for(int j = 0; (1<<j) <= i; j++)
            if((1<<j)&i) sum[i]++;
        if(g[i]) f[1][i][sum[i]] = 1;
    
    for(int i = 2; i <= n; i++)
        for(int j = 0; j < (1<<n); j++) 
            if(!g[j]) continue;
            for(int k = 0; k < (1<<n); k++) 
                if(k&j||(k<<1)&j||(k>>1)&j) continue;
                for(int l = 0; l <= m; l++)
                    f[i][j][l] += f[i-1][k][l-sum[j]];
            
        

    for(int i = 0; i < (1<<n); i++)
        ans += f[n][i][m];
    printf("%lld\n",ans);
    return 0;
View Code

 

题外话:

以前总觉得状压dp很难,一直不想写这个东西。写了才发现其实没什么...

只要努力就能克服困难!

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

P1896 [SCOI2005]互不侵犯

洛谷P1896 [SCOI2005]互不侵犯King

P1896 [SCOI2005]互不侵犯

P1896 [SCOI2005]互不侵犯

P1896 [SCOI2005]互不侵犯

洛谷 P1896 [SCOI2005]互不侵犯King