题目描述
农场主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;
}