30pts 板子状压求调,思路清晰易懂qwq
查看原帖
30pts 板子状压求调,思路清晰易懂qwq
304550
black_trees楼主2021/10/11 20:34

RT,思路大概是把所有不考虑贫瘠的情况的状态全部处理出来。

然后合法的话就看处理出来的状态 sta 是不是当前行的状态 yard 的子集。

fi,jf_{i,j} 表示的是考虑第 ii 行,扫描到编号为 jj 的 状态的方案数。

调试过之后发现 yardsta 这两个数组的处理都没问题,但是只有 30pts /kk


#include<bits/stdc++.h>
using namespace std;

const int si=14;
const int stasi=4096+10;
const int bitsi=4096+10;
const int p=100000000;
inline int mod(int x,int p){ return x<0?(x+p)-(((x+p)/p)*p):x-((x/p)*p);}
int n,m,cnt=0;
int f[si][stasi];
int sta[stasi];
int yard[si];

inline void init(int n){
	for(register int i=0;i<=n;++i){
		if((i&(i<<1))!=0 || (i&(i>>1))!=0) continue;
		sta[++cnt]=i;
		// printf("%d\n",sta[cnt]);
	}
}
inline bool valid(int l,int s){
	if(!((yard[l]&sta[s])==sta[s])) return false;
	return true;
}

int main(){
	memset(f,0,sizeof f);
	scanf("%d%d",&n,&m);
	for(register int i=1;i<=n;++i){
		for(register int j=1,k;j<=m;++j){
			scanf("%1d",&k);
			if(k) yard[i]+=(1<<(m-j));
		}
		// printf("%d\n",yard[i]);
	}
	init((1<<m)-1);
	for(register int i=1;i<=cnt;++i){
		f[1][i]=mod(1,p);
	}
	for(register int i=2;i<=n;++i){
		for(register int j=1;j<=cnt;++j){
			if(!valid(i,j)) continue;
			for(register int k=1;k<=cnt;++k){
				if((sta[j]&sta[k])!=0) continue;
				f[i][j]=mod(f[i][j]+f[i-1][k],p);
			}
		}
	}
	int res=0;
	for(register int i=1;i<=cnt;++i){
		res=mod(res+f[n][i],p);
	}
	return printf("%d\n",mod(res,p)),0;
}
2021/10/11 20:34
加载中...