状压DPCorn Fields牧场的安排

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了状压DPCorn Fields牧场的安排相关的知识,希望对你有一定的参考价值。

题意:
nm列牧场,每块都是一块土地,可以种草,要求两块草地不能相邻,且有的地不能种草,有多少种情况


状压DP:

一行的状态可以用一个数来表示,这个数的二进制形式就表示了一行的状态,二进制1表示有草,0代表无草

状态表示:

f [ i ] [ j ] f[i][j] f[i][j]表示前i行来说,第i行状态为j的总情况数

状态转移:

f [ i ] [ j ] = ∑ f [ i − 1 ] [ k ] f[i][j] = \\sum f[i-1][k] f[i][j]=f[i1][k],k代表第i-1行满足的状态
即当前行某个状态的情况等于前一行所有状态的情况和

  • check()用于检测一个状态是否有相邻的1
  • 初始化:只有当没有1相邻且可以种草(肥沃地方种草,不肥沃地方不能种草)才能初始化为1
  • 转移:前一行和当前行都需要
    • 没有相邻1
    • 可以种草(肥沃地方种草,不肥沃地方不能种草)
    • 且两行之间的1也不能相邻 ,即 ! ( j & k ) !(j \\& k) !(j&k)
#include<iostream>
typedef long long ll;
const int N = 13,mod = 1e9;

int f[N][1<<N],st[N];
int n,m;

bool check(int x)

	for(int i=0;i<m;i++)
		if((x>>i)&1 && (x>>i+1)&1)
			return false;
	return true;

int main()

	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		
			int x;
			scanf("%d",&x);
			st[i] <<= 1;
			st[i] += x;
		
	for(int i=0;i<1<<m;i++)
		if(check(i)&&((i|st[1])==st[1]))
			f[1][i] = 1;
	
	
	for(int i=2;i<=n;i++)
		for(int j=0;j<1<<m;j++)
			for(int k=0;k<1<<m;k++)
			
				if(((j|st[i])==st[i])&&((k|st[i-1])==st[i-1])&&(!(j&k))&&check(j)&&check(k))
					f[i][j] = (f[i][j] + f[i-1][k] ) % mod;
				
	
	ll res = 0;
	for(int i=0;i<1<<m;i++)
		res = (res + f[n][i]) % mod;
	
	printf("%lld\\n",res);
	return 0; 

往期优质文章推荐

领取大量学习资源

以上是关于状压DPCorn Fields牧场的安排的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1725 [Usaco2006 Nov]Corn Fields牧场的安排(状压dp)

BZOJ1725[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

bzoj1725/Usaco2006 NovCorn Fields牧场的安排——状压dp

bzoj1725[Usaco2006 Nov]Corn Fields牧场的安排*

BZOJ1725: [Usaco2006 Nov]Corn Fields牧场的安排

bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排(状态压缩DP)