acwing 3494 国际象棋 状态压缩dp (qwq)2022/03/06

#include<iostream>
using namespace std;
const int N=1<<6;
const int M=110;
const int T=30;
const int mod=1e9+7;
typedef long long ll;
ll f[M][N][N][T];//f[i][a][b][t] i 代表前i列 a代表前前列,b代表前面一列的状态集合 t代表已经用过多少个棋子
int lowit(int x){//计算当前列增加了多少个棋子
    int res=0;
    for(;x;x-=(x&-x))res++;
    return res;
}
int main(){
    int n,m,k;
    cin>>n>>m>>k;
    int maxn=1<<n;
    f[0][0][0][0]=1;//初始化
    for(int i=1;i<=m;i++)
        for(int a=0;a<maxn;a++)
            for(int b=0;b<maxn;b++)
                if((a>>2)&b||a&(b>>2))continue;//判断前前列和前列有没有发生冲突剪枝
                else
                    for(int c=0;c<maxn;c++){
                        if((c>>2)&b||c&(b>>2))continue;//判断前列和当前列有没有发生冲突
                        if((c>>1)&a||c&(a>>1))continue;//判断前前列和当前列有没有发生冲突
                        int t=lowit(c);
                        for(int tt=t;tt<=k;tt++)//背包计算个数
                            f[i][b][c][tt]=(f[i][b][c][tt]+f[i-1][a][b][tt-t])%mod;
                    }
    int res=0;
    for(int i=0;i<maxn;i++)//对前前列和前列不同的状态最终有多少个可以摆放的方案数
        for(int j=0;j<maxn;j++)
            res=(res+f[m][i][j][k])%mod;
    cout<<res;
}

作者:沙烬
链接:https://www.acwing.com/solution/content/43484/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三粒小金子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值