1. 程式人生 > >BZOJ1725 [Usaco2006 Nov]Corn Fields牧場的安排

BZOJ1725 [Usaco2006 Nov]Corn Fields牧場的安排

題意

Farmer John新買了一塊長方形的牧場,這塊牧場被劃分成M列N行\((1 \leq M \leq 12, 1 \leq N \leq 12)\),每一格都是一塊正方形的土地。FJ打算在牧場上的某幾格土地裡種上美味的草,供他的奶牛們享用。遺憾的是,有些土地相當的貧瘠,不能用來放牧。並且,奶牛們喜歡獨佔一塊草地的感覺,於是FJ不會選擇兩塊相鄰的土地,也就是說,沒有哪兩塊草地有公共邊。當然,FJ還沒有決定在哪些土地上種草。 作為一個好奇的農場主,FJ想知道,如果不考慮草地的總塊數,那麼,一共有多少種種植方案可供他選擇。當然,把新的牧場荒廢,不在任何土地上種草,也算一種方案。請你幫FJ算一下這個總方案數。

分析

狀壓裸題。

就每行建狀態\(f(i,s)\)表示\(i\)行種草狀態為\(s\)的方案數即可。

看到Farmer John和他的奶牛的一般都是水題。

程式碼

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0;
    rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>T read(T&x)
{
    return x=read<T>();
}
using namespace std;
typedef long long ll;

co int MAXN=12,mod=100000000;
int m,n;
int mp[MAXN],f[MAXN][1<<MAXN];
int ans;

int add(int x,int y)
{
    x+=y;
    return x>=mod?x-mod:x;
}

void dp()
{
    for(int i=mp[0];i>=0;i=!i?-1:(i-1)&mp[0])
        if((i & (i >> 1)) == 0)
            f[0][i]=1;
    for(int i=1;i<m;++i)
        for(int j=mp[i-1];j>=0;j=!j?-1:(j-1)&mp[i-1])
            if(f[i-1][j])
                for(int k=mp[i];k>=0;k=!k?-1:(k-1)&mp[i])
                    if((j & k) == 0 && (k & (k >> 1)) == 0)
                        f[i][k]=add(f[i][k],f[i-1][j]);
    for(int i=mp[m-1];i>=0;i=!i?-1:(i-1)&mp[m-1])
        ans=add(ans,f[m-1][i]);
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(m);read(n);
    for(int i=0;i<m;++i)
        for(int j=0;j<n;++j)
            mp[i]=mp[i]<<1|read<int>();
    dp();
    printf("%d\n",ans);
    return 0;
}