洛谷P1879题解

P1879

Solution

分析

首先把矩阵存在 \(a[i][j]\)
然后用一个数组b存每一行i,里的状态,用加法来进计算
用一个 \(meiju\) 数组 枚举出 1-2^n (左开右闭区间)所有满足题意的方案
初始化 \(f[0][0]\) 啥都不种也是一种方案
双重循环,分别枚举行数和 1-2^n(左开右闭区间)的所有方案数
如果此时j合法即 \(meiju[j]\) 存在,并且 \(j\) 必须是 \(b[i]\) 的一个子集
然后继续枚举k 1-2^n(左开右闭区间)当k和j没有交集时进行状态转移 \(f[i][j]\) = ( \(f[i][j]\) + \(f[i-1][k]\) ) % \(Mod\)
此时是正序枚举,若倒叙可将 \(f[i-1][k]\) 改为 \(f[i+1][k]\)

code

/*
work by Simon
*/ 
#include<bits/stdc++.h>
#define maxn 4096
using namespace std;
const int Mod=1e9;
int n,m,ans;
int a[13][13],b[maxn],meij[maxn],f[13][maxn];
bool pd(int k)
{
	if((!(k&(k<<1)))&&(!(k&(k>>1))))
		return true;
	return false;
}
int main()
{
	std::ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	int MAX=(1<<m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			{
				b[i]=(b[i]<<1)+a[i][j];
			}
	f[0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<MAX;j++)
			{
				if(pd(j)&&((b[i]&j)==j))
					for(int k=0;k<MAX;k++)
						if((k&j)==0)
							f[i][j]=(f[i][j]+f[i-1][k])%Mod;
			}
	for(int i=0;i<MAX;i++)
		ans=(ans+f[n][i])%Mod;
	cout<<ans;
	return 0;
 } 
posted @ 2021-11-14 21:33  Simon_...sun  阅读(84)  评论(0)    收藏  举报