BZOJ 1725 Corn Fields

状压DP
DP[i][j]表示已放完i行,第i行放置状态为j的方案数
预处理出所有满足一行中无两格相邻的放置方案
列数为12时这个方案数少于400
枚举方案转移,需要满足与上一行无交且是Map(可行格)的子集

#include <cstdio>

const int MAXN=12;
const int MAXM=12;
const int MOD=100000000;

int N, M, Val;
int Map[MAXN];
int DP[MAXN][1<<MAXM];

bool Test(int a){
    bool ret=true;
    for(int i=0, p=0;i<M;++i, a>>=1){
        if(p>0 && (a&1))    {ret=false;break;}
        p=a&1;
    }
    return ret;
}

int Put[1<<MAXM], Pcnt;

int main(){
    
    scanf("%d%d", &N, &M);
    for(int i=0;i<N;++i){
        Map[i]=0;
        for(int j=0, a;j<M;++j){
            scanf("%d", &a);
            if(a>0) Map[i]+=(1<<j);
        }
    }
    
    for(int i=(1<<M)-1;i>=0;--i)
        if(Test(i))
            Put[++Pcnt]=i;
    
    //for(int i=1;i<=Pcnt;++i)
    //  printf("%d\n", Put[i]);
    
    for(int i=1;i<=Pcnt;++i){
        if((Put[i]&Map[0])==Put[i]){
            DP[0][Put[i]]=1;
        }
    }
    
    for(int i=0;i+1<N;++i){
        for(int j=(1<<M)-1;j>=0;--j){
            if(DP[i][j]<=0) continue;
            for(int p=1;p<=Pcnt;++p){
                if((Put[p]&Map[i+1])==Put[p] && (Put[p]&j)==0){
                    DP[i+1][Put[p]]+=DP[i][j];
                    if(DP[i+1][Put[p]]>=MOD)    DP[i+1][Put[p]]-=MOD;
                }
            }
        }
    }
    
    int Ans=0;
    for(int j=(1<<M)-1;j>=0;--j){
        Ans+=DP[N-1][j];
        if(Ans>=MOD)    Ans-=MOD;
    }
    printf("%d\n", Ans);
    
    return 0;
}

转载于:https://www.cnblogs.com/Pickupwin/p/9628648.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值