洛谷-1879 [USACO06NOV]玉米田Corn Fields

本文探讨了一个经典的算法问题——牧场种草问题,通过状态压缩动态规划(DP)解决该问题。在一个M行N列的牧场中,部分土地肥沃可种植,部分贫瘠不可种植。由于奶牛喜独享草地,故相邻土地不可同时种植。文章详细介绍了如何通过状态压缩DP求解牧场种植方案总数,并给出了具体的代码实现。

题目描述
农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。
遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。
John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)
输入输出格式
输入格式:
第一行:两个整数M和N,用空格隔开。
第2到第M+1行:每行包含N个用空格隔开的整数,描述了每块土地的状态。第i+1行描述了第i行的土地,所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块土地不适合种草。
输出格式:
一个整数,即牧场分配总方案数除以100,000,000的余数。

输入输出样例
输入样例#1:
2 3
1 1 1
0 1 0

输出样例#1:
9

解释:直接状态压缩dp,dp[i][j]:1-i行,且第i行状态为j的时候的方案数。

#include<iostream>
#define mod 100000000
using namespace std;
int G[15]={0};
int dp[15][(1<<12)+5]={0};
int n=0,m=0;
bool check(int x){
    int f=0;
    while(x){
        if((x&1)&&((x&1)==f)) return 0;
        f=x&1;
        x>>=1;
    }
    return 1;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1,v;j<=m;j++){
            cin>>v;
            G[i]|=(v<<(j-1));
        }
    }
    for(int i=0;i<(1<<m);i++){
        if((i&G[1])==i&&check(i)){
            dp[1][i]++;
        }
    }
    for(int i=2;i<=n;i++){
        for(int j=0;j<(1<<m);j++){
            if((j&G[i-1])!=j||!check(j)) continue;
            for(int k=0;k<(1<<m);k++){
                if((k&G[i])!=k||!check(k)) continue;
                if((j&k)==0){
                    dp[i][k]+=dp[i-1][j];
                    dp[i][k]%=mod;
                }
            }
        }
    }
    int ret=0;
    for(int i=0;i<(1<<m);i++){
        if(check(i)) ret+=dp[n][i];
        ret%=mod;
    }
    cout<<ret<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值