JZOJ 1266. 玉米田

目录:


题目:

单击查看题目


分析:

先用二进制表示每一行的是否可以放置的状态。
然后用 s t a t e [ i ] 来表示只计算单行第 i 种状态是否合法。
然后每次将状态左移和右移一位然后用&运算判断是否合法就行了。
之后我们开始dp
f [ i ] [ j ] 表示第i行第j种状态的方案数。然后我们枚举上一行的状态 k ,然后判断两个状态是否合法。
对于 f 的初始化,则是 f [ 0 ] [ 0 ] 等于1


代码:

#pragma GCC optimize("Os")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int state[4096],t[13][13],e[13],f[13][4096];
int main()
{
/*  freopen("cowfood.in","r",stdin);
    freopen("cowfood.out","w",stdout);*/
    int n=read(),m=read(),ms;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        t[i][j]=read();
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        e[i]=(e[i]<<1)+t[i][j];
    ms=1<<m;
    for(int i=0;i<ms;i++)
      state[i]=((i&(i<<1))==0)&&((i&(i>>1))==0);
    f[0][0]=1;
    for(int i=1;i<=n;i++)
      for(int j=0;j<ms;j++)
        if(state[j]&&((j&e[i])==j))
          for(int k=0;k<ms;k++)
            if((k&j)==0)
              f[i][j]=(f[i][j]+f[i-1][k])%1000000000;
    int ans=0;
    for(int i=0;i<ms;i++)
      ans=(ans+f[n][i])%1000000000;
    printf("%d",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/81089149