*点击

[USACO06NOV] Corn Fields G

题目

Description

农场主 John 新买了一块长方形的新牧场,这块牧场被划分成 M 行 N列 (1≤M≤12,1≤N≤12),每一格都是一块正方形的土地。 John 打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是 John 不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John 想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

Input

第一行:两个整数 M 和 N,用空格隔开。

第 22 到第 M+1 行:每行包含 N 个用空格隔开的整数,描述了每块土地的状态。第 i+1 行描述了第 行的土地,所有整数均为 或 1 ,是 1 的话,表示这块土地足够肥沃,0 则表示这块土地不适合种草。

Output

一个整数,即牧场分配总方案数除以 100,000,000的余数。

Sample Input

2 3
1 1 1
0 1 0

Sample Output

9

思路

一道状压$dp$题;

用$dp[i][k]$表示第$i$行的种植状态$k$;

把不符合种植条件的状态去掉;

再枚举上一行的状态;

若两行状态没有相邻种植,$dp[i][k]$ 加上上一行方案再取模即可;

 


 

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll _=13;
ll n,m;
ll a[13][13],dp[13][1<<12];
int main()
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=m;j++)
        scanf("%lld",&a[i][j]);
    dp[0][0]=1;
    for(ll i=1;i<=n;i++)
    for(ll k=0;k<=(1<<m)-1;k++)
    {
        if(k&(k>>1)) continue;//不能左右相邻种植
        ll flag=0;
        for(ll j=1;j<=m;j++)
        if(a[i][j]==0&&k&(1<<(j-1)))//只能在肥沃的土地上种植
        {
            flag=1;
            break;
        }
        if(flag) continue;
        for(ll l=0;l<=(1<<m)-1;l++)
        if(!(k&l))//与上一行状态没有相邻种植
            dp[i][k]=(dp[i][k]+dp[i-1][l])%100000000;//加上方案
    }
    ll ans=0;
    for(ll i=0;i<=(1<<m)-1;i++)
        ans=(ans+dp[n][i])%100000000;
    printf("%lld",ans);
    return 0;
}

 

 

 

 

posted @ 2024-12-16 22:14  木偶人-怪咖  阅读(3)  评论(0编辑  收藏  举报
*访客位置3D地图 *目录