jzoj1266,P1879-[USACO06NOV]玉米田Corn Fields【状态压缩,dp】

正题

评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1879


大意

有n*m的矩阵,有些地方可以放,有些不可以放,不可以相邻的放,求放置方法总数。


解题思路

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


code

#include<cstdio>
#include<algorithm>
#define MN 4100
using namespace std;
int n,m,c,f[MN],F[14][MN],state[MN],ans,MS;
int main()
{
    //freopen("cowfood.in","r",stdin);
    //freopen("cowfood.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
      for (int j=1;j<=m;j++)
      { 
        scanf("%d",&c);
        f[i]=(f[i]<<1)+c;
      }
    MS=1<<m;
    for (int i=0;i<MS;i++)
        state[i]=!(i&(i<<1)||i&(i>>1));
    F[0][0]=1;
    for (int i=1;i<=n;i++)
      for (int j=0;j<MS;j++)
        if (state[j]&&(j&f[i])==j)
          for (int k=0;k<MS;k++)
            if (!(k&j))
              F[i][j]=(F[i][j]+F[i-1][k])%100000000;
    for (int i=0;i<MS;i++)
      ans=(ans+F[n][i])%100000000;
    printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/mr_wuyongcong/article/details/81088120
今日推荐