【状压dp】 洛谷 P1896 [SCOI2005]互不侵犯

P1896 [SCOI2005]互不侵犯

题目描述

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

注:数据有加强(2018/4/25)

输入输出格式

输入格式:

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

输出格式:

所得的方案数

输入输出样例

3 2

16

#include <bits/stdc++.h>
using namespace std;
long long dp[10][1<<9][82]; //第i行j状态下放了k个国王的最大方案数
int c[1<<9];//记录一行中每种状态下的国王数量

void init()
{
    for(int i=0;i<(1<<9);i++)
    {
        int k=i;
        for(int j=0;j<9;j++)
        {
            c[k]+=(i>>j&1);
        }
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    init();
    long long ans=0;
    dp[0][0][0]=1;
    for(int k=1;k<=m;k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int S=0; S<(1<<n); S++)
            {
                if(S&(S<<1)) continue; //国王相邻,continue;
                if(k-c[S]<0) continue;   //国王超过k,continue;
                for(int s=0; s<(1<<n); s++)
                {
                    if((S&s)||((S>>1)&s)||((S<<1)&s)) continue; //判断与上一行的状态
                    dp[i][S][k]+=dp[i-1][s][k-c[S]];
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<(1<<n);j++)
                ans+=dp[i][j][m];
        }
    }
    printf("%lld\n",ans);
    return 0;
}
扫描二维码关注公众号,回复: 2659005 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_41037114/article/details/81411262