P1879 玉米田Corn Fields题解

洛谷 P1879
链接: P1879 玉米田Corn Fields.

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

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

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

input

2 3
1 1 1
0 1 0

output

9

看到两个数M N都小于12,第一反应就是状压,用二进制来表示每一行的状态,例如,j=13时,j 用二进制表示为 1101 ,表示1号位置种草,2号位置种草,3号位置不种草,4号位置种草。

首先输入M N ,然后输入地图,这里有一种快捷方式记录地图,相当于把每一行的状态压缩为一个数字存储,列如样例第一行 1 1 1 压缩为 7 ,这样会使后面的操作简单些

    for(int i=1;i<=m;i++)
        for(int j=0;j<n;j++){
            int x;
            cin>>x;
            mp[i]|=(x<<j);//记录地图信息
        }

本题有两个约束条件,第一是不能 0 位置种草,第二时不能有连续的草丛

先解决第一个条件,由于之前已经记录了压缩后的地图状态了,假设此时第 i 行地图状态为mp[i] ,第i 行的状态为k , 假设 mp[i] 二进制的第 j 位为0,那么k的第 j 位就只能是0,如果 mp[i]j 位为1,那么k的第 j 位可以是 01,这里我们用一种运算—— |,或运算
用 (mp[i] | k) == mp[i] 来判断合法
画图理解下
P1879 玉米田Corn Fields题解_第1张图片
第二个条件比较简单,设当前行状态为 j ,上一行状态为 k
j & ( j >>1 )可以快速判断是否有连续的 1
j & k 可以快速判断是否与上一行状态有冲突

两个条件都满足时候 转移状态 dp[i] [j] += dp[i-1] [l]

附上代码

#include<bits/stdc++.h>
using namespace std;
int n,m,sum=0,mod=1e9;
int mp[105]={0},dp[13][1<<12];//mp存储地图情况,dp枚举每一种状况
int main(){
    cin>>m>>n;
    for(int i=1;i<=m;i++)
        for(int j=0;j<n;j++){
            int x;
            cin>>x;
            mp[i]|=(x<<j);//记录地图信息
        }
    for(int l=0;l<(1<<n);l++){
        if((l&(l>>1)))  continue;   
        if((mp[1]|l)!=mp[1])    continue;
        dp[1][l]=1; 
    }//初始化第一行的情况
    for(int i=2;i<=m;i++){
        for(int j=0;j<(1<<n);j++){//当前行 
            int flag=1;
            if((j&(j>>1)))  continue;//判断当前行是否有相邻的情况 
            if((mp[i]|j)!=mp[i]) continue;//判断是否在0的位置种草了
            for(int l=0;l<(1<<n);l++){
                if((l&(l>>1)))  continue;//判断上一行是否有相邻的情况 
                if((mp[i-1]|l)!=mp[i-1]) continue;
                if(l&j) continue;   //判断此行和上一行是否相邻 
                dp[i][j]+=dp[i-1][l];
                dp[i][j]%=mod;  
            }
        }
    }
    for(int i=0;i<(1<<n);i++){
        sum+=dp[m][i];
        sum%=mod;
    }
    cout<<sum;
    return 0;
} 

你可能感兴趣的:(P1879 玉米田Corn Fields题解)