Corn Fields 玉米田

这题是状压dp的模板题。

至于状压是什么,自己上网查吧,我在这里不多说。

预处理:

1.\(f[i]\)表示第\(i\)行的玉米田可行方案;

\(ok[i]\)表示\(i\)状态是否是可行解。

判断方法:与\(i<<1\)\(i>>1\) &后 均为0,证明脑补一下就可以了。

之后状压dp

\(dp[i][j]\) 表示枚举到第\(i\)行,状态为\(j\)的方案总数

\(dp[i][j]+=dp[i-1][k]\) 当且仅当 \(ok[i]\)\(j\)&\(f[i]==j\) \(j\)&\(k==0\)

答案是 $\sum_{i=0}^{1<<m-1} dp[n][i] $

注意取模

#include <cstdio>
using namespace std ;
const int p = 100000000 ;
int dp[13][5000],a[13][13],f[13],ok[5000];
int n,m ;
int main(){
	scanf("%d%d",&n,&m) ;
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
	scanf("%d",&a[i][j]) ;
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
	f[i]=(f[i]<<1)+a[i][j] ;
	for (int i=0;i<(1<<m);i++) ok[i]=((!(i&(i<<1)))&&(!(i&(i>>1)))) ;
	dp[0][0]=1 ;
	for (int i=1;i<=n;i++)
	for (int j=0;j<(1<<m);j++)
	if (ok[j] && ((j&f[i])==j)){
		for (int k=0;k<(1<<m);k++) if (!(j&k)) dp[i][j]=(dp[i][j]+dp[i-1][k])%p ;
	}
	int ans=0;
	for (int i=0;i<(1<<m);i++) ans=(ans+dp[n][i])%p ;
	printf("%d\n",ans) ;
} 
posted @ 2018-08-08 08:23  harryhqg  阅读(111)  评论(0编辑  收藏  举报