bzoj 1725 Corn Fields

Written with StackEdit.

Description

Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行\((1<=M<=12; 1<=N<=12)\),每一格都是一块正方形的土地。FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。当然,FJ还没有决定在哪些土地上种草。 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮FJ算一下这个总方案数。

Input

  • 第1行: 两个正整数\(M\)\(N\),用空格隔开
  • \(2..M+1\)行: 每行包含\(N\)个用空格隔开的整数,描述了每块土地的状态。输入的第\(i+1\)行描述了第i行的土地。所有整数均为\(0\)\(1\),是\(1\)的话,表示这块土地足够肥沃,\(0\)则表示这块地上不适合种草.

    Output

    \(1\)行: 输出一个整数,即牧场分配总方案数除以\(100000000\)的余数

    Sample Input

    2 3
    1 1 1
    0 1 0

    Sample Output

    9

Solution

  • 状压\(dp\)的入门题.
  • 注意每一行有共同的限制,即不能有相邻的.可以预处理此条件下合法的方案,转移时再加上其他限制即可.
  • 可以滚成一维,但没必要.
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int P=1e8;
inline int add(int a,int b)
{
    return (a + b) % P;
}
inline int mul(int a,int b)
{
    return 1LL * a * b % P;
}
const int MAXN=13;
const int MAXS=1<<13;
int n,m;
int fix[MAXN][MAXN];
int f[MAXN][MAXS];
int g[MAXS],tot=0;
vector<int> G[MAXN];
inline int judge(int st)
{
    int ls=0;
    while(st)
        {
            int p=st&1;
            if(p && ls)
                return 0;
            ls=p;
            st>>=1;
        }
    return 1;
}
int check(int cur,int r)
{
    int cnt=1;
    while(cur)
        {
            int p=cur&1;
            if(p && fix[r][cnt]==0)
                return 0;
            ++cnt;
            cur>>=1;
        }
    return 1;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            fix[i][j]=read();
    int S=1<<m;
    for(int i=0;i<S;++i)
        if(judge(i))
            g[++tot]=i;
    G[0].push_back(0);
    f[0][0]=1;
    int ans=0;
    for(int i=1;i<=n;++i)
        {
            int sizls=G[i-1].size();
            for(int p=1;p<=tot;++p)
                {
                    int st=g[p];
                    if(check(st,i))
                        {
                            G[i].push_back(st);
                            for(int j=0;j<sizls;++j)    
                            {
                                int k=G[i-1][j];
                                if(!(st&k))
                                    f[i][st]=add(f[i][st],f[i-1][k]);
                            }
                        }
                    if(i==n)
                        ans=add(ans,f[i][st]);
                }
        }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jklover/p/10002780.html
今日推荐