SGU223_状态压缩

下午花了两个小时把Yali中学 陈丹琦的《基于连通性状态压缩的动态规划问题》啃完,,,

 

插头DP还真是个麻烦的东西。。。

 

相较SGU223算一个水题了,

给定N*N的棋盘,摆放m个不相互攻击的棋子,棋子攻击范围为相邻8个位置。求方案数。

dp[i][j][k],第i行,状态为j,放了k个棋子的方案数,dp[i][j][k] = sum(dp[i-1][jj][k - cnt(j)])

 详见代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#define LL long long
#define N 11
int n;
int m;

LL dp[11][1024][111];
int cnt[1024];

int get_cnt(int x)
{
    int res = 0;
    while (x)
    {
        if (x % 2 == 1)
            res++;
        x /= 2;
    }
    return res;
}
bool check(int x)
{
    if ((((x<<1)&x) == 0) && (((x>>1))&x) ==0)
        return 1;
    return 0;
}
bool calc(int x,int y)
{
    if (((x&y) == 0) && (((x<<1)&y)==0) && (((x>>1)&y)==0))
        return 1;
    return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(dp,0,sizeof(dp));
    memset(cnt,-1,sizeof(cnt));
    for (int i=0; i<=(1<<n)-1; i++)
    {
        if (check(i))
        {
            cnt[i] = get_cnt(i);
        }
    }
    dp[0][0][0] = 1;
    for (int i=1; i<=n; i++)
        for (int j=0; j<=(1<<n)-1; j++)
            if (cnt[j]>=0)
            {
                for (int k=0; k<=(1<<n)-1; k++)
                    if (cnt[k]>=0 && calc(k,j))
                    {
                        for (int s=0; s<=m; s++)
                        {
                            if (s - cnt[j]>=cnt[k])
                            {
                                dp[i][j][s] += dp[i-1][k][s - cnt[j]];
                            }
                        }

                    }
            }
    LL ans = 0;
    for (int j=0;j<=(1<<n)-1;j++)
        if (cnt[j]>=0){
            ans += dp[n][j][m];
        }

    printf("%I64d\n",ans);
    return 0;
}
SGU223

 

转载于:https://www.cnblogs.com/wangsouc/articles/3228444.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值