jzoj 1266. 玉米田(cowfood.pas/c/cpp)

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[i1,k](k & j ) ! = 0 , j 合 法 j)!=0,j 合法 j)!=0j//上一行的格子没种,这一行的格子能种。

#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);
}

你可能感兴趣的:(赛题,状压dp)