POJ3254-Corn Fields(状态压缩)

Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can’t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.

Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

Input
Line 1: Two space-separated integers: M and N
Lines 2…M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)
Output
Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
Hint
Number the squares as follows:
1 2 3
4

There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.

分析:

题意:
在一块n行m列的土地上种草,如果(x,y)的值为1,则这块地肥沃,可以种草;如果值为0,那么这块土地就比较贫瘠,无法种植,现在农场主要在这些土地上种草并放养奶牛,不放养的肥沃的土地可以不种,但是这些奶牛有一个要求,就是这些奶牛不能成为邻居,即放牧的地没有公共边,问在这样的土地上有多少种不同的种植方法?

解析:
这不是我的第一道状态压缩的题了,但是开始看这道提还是一筹莫展,太菜了!

我们将每块地种和不种分别用1和0表示,那么我们以一行3块土地来看,那么它的种植方法有:

种植的方法 二进制 十进制
全不种 000 0
只种第一块 100 4
只种第二块 010 2
只种第三块 001 1
种第一、二块 110 6
种第二、三块 011 3
种第一、三块 101 5
全种 111 7

那么他们对应的值各不相同,且恰为23种,每个数对应一种方法,这就是状态压缩!

我们在根据题目的要求对一些情况进行选择!

代码:

#include<iostream>
#include<cstdio>
#define N 15
#define Mod 100000000

using namespace std;

int n,m;
int map[N][N];
int dp[N][1<<12+10];

bool cmp(int a,int b)
{
	if(b&(b<<1)) //如果有两个1紧挨着,那么在同一行上面是不符合条件的,就不用继续检测同列了
		return false;
	for(int i=1;i<=m;i++)//判断是否在不肥沃的土地上种上了草 
	{
		if(!map[a][i]) //若这处是不能种植的
		{
			if(((1<<(m-i))&b)!=0) //但是这种状态下此处种了树	
			return false;
		}
	}
	return true;
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				scanf("%d",&map[i][j]);
			}
		}
		dp[0][0]=1;
		long long sum=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<(1<<m);j++)
			{
				if(cmp(i,j))
				{
					for(int k=0;k<(1<<m);k++)
					{
						if(!(k&j))
							dp[i][j]+=dp[i-1][k]; 
					}
				}
			}
		}
		for(int i=0;i<(1<<m);i++)
		{
			sum=(sum+dp[n][i])%Mod;
		}
		printf("%lld",sum);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43357583/article/details/106160264