Description
农民 John 购买了一处肥沃的矩形牧场,分成M*N(1 <= M <= 12; 1 <= N <= 12)个格子。他想在那里的一些格子中种植美味的玉米。遗憾的是,有些格子区域的土地是贫瘠的,不能耕种。精明的 FJ 知道奶牛们进食时不喜欢和别的牛相邻,所以一旦在一个格子中种植玉米,那么他就不会在相邻的格子中种植,即没有两个被选中的格子拥有公共边。他还没有最终确定哪些格子要选择种植玉米。 作为一个思想开明的人,农民 John 希望考虑所有可行的选择格子种植方案。由于太开明,他还考虑一个格子都不选择的种植方案!请帮助农民 John 确定种植方案总数。
Input
Line 1: 两个用空格分隔的整数 M 和 N
Lines 2…M+1: 第 i+1 行描述牧场第i行每个格子的情况, N 个用空格分隔的整数,表示 这个格子是否可以种植(1 表示肥沃的、适合种植,0 表示贫瘠的、不可种植)
Output
Line 1: 一个整数: FJ 可选择的方案总数 除以 100,000,000 的余数。
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
Data Constraint
Hint
【样例说明】
给可以种植玉米的格子编号:+
1 2 3
4
只种一个格子的方案有四种 (1, 2, 3, 或 4),种植两个格子的方案有三种 (13, 14, 或 34),种植三个格子的方案有一种 (134),还有一种什么格子都不种。 4+3+1+1=9。
//written by zzy
在一个图中,只能在 1 1 1 的格子种,且种了的格子上下左右不能种,求种的方案数。
观看数据规模,不难发现是状压dp,状态 x x x 二进制下的 第 i i i 为 1 1 1 表,第 i i i 种了
设 f [ i , j ] f[i,j] f[i,j] 为第 i i i 行,状态为 j j j 的方案数,考虑如何转移,
先将地图,每一行不合法的状态处理处来
因为只有上一行能影响这一行的转移,所以易得
f [ i , j ] = ∑ f [ i − 1 , k ] , ( k f[i,j]=∑f[i-1,k],(k f[i,j]=∑f[i−1,k],(k & j ) ! = 0 , j 合 法 j)!=0,j 合法 j)!=0,j合法//上一行的格子没种,这一行的格子能种。
#include
#include
#include
#define N 14
#define Mod 100000000
using namespace std;
int i,j,k,n,m,ans,x;
int map[N],f[N][1<<N];
bool g[N];
int main()
{
freopen("cowfood.in","r",stdin);
freopen("cowfood.out","w",stdout);
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++) {
scanf("%d",&x);
if (x) map[i]|=1<<(m-j);
}
for (i=0;i<=(1<<m)-1;i++) g[i]=1;
for (i=0;i<=(1<<m)-1;i++)
for (j=2;j<=m;j++)
if (((i&(1<<(j-1)))!=0)&&((i&(1<<(j-2)))!=0))
g[i]=0;
for (j=0;j<=(1<<m)-1;j++)
if (g[j]&&(map[1]|j)==map[1]) f[1][j]=1;
for (i=2;i<=n;i++)
for (j=0;j<=(1<<m)-1;j++)
if (g[j]&&((map[i]|j)==map[i]))
for (k=0;k<=(1<<m)-1;k++)
if ((k&j)==0)
f[i][j]=(f[i][j]+f[i-1][k])%Mod;
for (j=0;j<=(1<<m)-1;j++)
ans=(ans+f[n][j])%Mod;
printf("%d",ans);
}