Corn Fields

Corn Fields

给出一个\(m\times n\)的矩形网格图,给出网格图中障碍物的位置,求向其中放若干个棋子互不相邻(当然也可以没有)的方案数\(mod\ 10^8\)\(n,m\times 12\)

显然数据范围很小,考虑进制压缩,于是设\(f[i][j]\)表示前i行,第i行状态为j的方案数,其中j有1的位置表示有棋子,可以先预处理出一行摆棋子合法的方案,记做\(a[i][j]\)表示第i行第j个合法状态,因此有

\[f[i][j]=\sum_{k=1}^{|a[i]|}f[i-1][k](!a[i][k]\&a[i-1][k]) \]

边界:\(f[0][1]=a[0][1]=0\)

答案:\(\sum_{i=1}^{|a[m]|}f[m][i]\)

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define cjx 100000000
using namespace std;
char c[13];
int dp[13][4097],a[13][4097],
    at[13];
il void get(char&);
int main(){
    int n,m,li;scanf("%d%d",&n,&m);
    li=(1<<m)-1;
    for(int i(1),j,k;i<=n;++i){
        for(j=0;j<m;++j)get(c[j]);
        for(j=0;j<=li;++j){
            for(k=m-1;k>=0;--k)
                if(j>>k&1){
                    if(c[k]=='0')break;
                    if(j>>(k+1)&1)break;
                }
            if(k<0)a[i][++at[i]]=j;
        }
    }++at[0],dp[0][1]=1;
    for(int i(1),j,k;i<=n;++i)
        for(j=at[i];j;--j)
            for(k=at[i-1];k;--k){
                if(a[i][j]&a[i-1][k])continue;
                dp[i][j]+=dp[i-1][k];
                if(dp[i][j]>cjx)dp[i][j]-=cjx;
            }int ans(0);
    for(int i(1);i<=at[n];++i)
        (ans+=dp[n][i])%=cjx;printf("%d",ans);
    return 0;
}
il void get(char &c){
    while(c=getchar(),c==' '||c=='\n'||c=='\r');
}
posted @ 2019-06-13 08:00  a1b3c7d9  阅读(189)  评论(0编辑  收藏  举报