洛谷P1896_状压dp

本弱第一篇状压dp(在看了题解的前提下做的)


在n*n个格子内放m个国王,要求国王的四周即周围8个格子不能再有国王,求不同的放置方案数
将任意一行的一个状态看作是n位的二进制数,1表示放了国王,0表示没有放
dp[i][j][k] 表示前i行第j个状态,已经放置了k个国王的方案数;
can[i]第i个状态的数字,num[i]第i个状态的1的个数;

#include <cstdio>
#include <cstring>

using namespace std;

typedef long long LL;

int n, m;//n*n的格子放m个
LL dp[11][1111][111];//前i行,第j个状态,共有k个国王的方案数

int can[1111], num[1111];//满足条件的数,以及它的含1的个数
int tot;

int getnum(int x)
{
    int ret = 0;
    while(x) ret += (x&1), x>>=1;
    return num[tot] = ret;
}

int main()
{
    int i, j, k, l, x, y;
    scanf("%d %d", &n, &m);
    memset(dp, 0, sizeof(dp));
    int maxn = (1<<n)-1;
    tot = 0;
    for(i = 0; i <= maxn; ++i)
        if(!(i&(i<<1)))//若二进制没有连续的1
            can[++tot] = i, dp[1][tot][getnum(i)] = 1;
    for(i = 2; i <= n; ++i)//枚举行号
        for(j = 1; j <= tot; ++j)//枚举第i行的状态
    {
        x = can[j];
        for(k = 1; k <= tot; ++k)//枚举第i-1行的状态
        {
            y = can[k];
            if((x&y) || (x&(y<<1)) || (x&(y>>1))) continue;
            for(l = 0; l <= m; ++l) dp[i][j][num[j]+l]+=dp[i-1][k][l];//更新状态
        }
    }
    LL ans = 0;
    for(i = 1; i <= tot; ++i) ans += dp[n][i][m];
    printf("%lld\n", ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值