30pts 求助,初学状压
查看原帖
30pts 求助,初学状压
481621
Zhang_Wenjie楼主2024/8/18 13:43

思路是 先预处理出所有同行不相邻的合法状态,

dp 的时候额外判断一下对该行调用的状态是否合法(状态中种了草的地方是否都可以种草),

然后如果当前行与上一行的状态不矛盾,就累加贡献

#include <bits/stdc++.h>
#define re register int 

using namespace std;
typedef long long LL;
const int maxs = 8200, mod = 1e8;

int n, m, g[20][20], ok[maxs], num;
LL f[20][maxs];

inline void init()
{
	for (re j = 1; j <= m; j ++) g[0][j] = 1;
	for (re s = 0; s < (1 << m); s ++)
	{
		if ((((s << 1) | (s >> 1)) & s) == 0) ok[++ num] = s;
	}
}

inline bool check(int s, int i)
{
	int j = m;
	bool flag = false;
	
	while (s)
	{
		if ((s & 1) && !g[i][j])
		{
			flag = true;
			break;
		}
		s >>= 1;
		j --;
	}
	return flag; 
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> m;
	for (re i = 1; i <= n; i ++)
		for (re j = 1; j <= m; j ++) cin >> g[i][j];
	init();
	
	f[0][0] = 1;
	for (re i = 1; i <= n; i ++)
		for (re u = 1; u <= num; u ++)
		{
			int su = ok[u];
			if (check(su, i)) continue;
			for (re v = 1; v <= num; v ++)
			{
				int sv = ok[v];
				if (check(sv, i - 1)) continue;
				if ((su & sv) == 0) f[i][sv] += f[i - 1][su];
			}
		}
	LL res = 0;
	for (re s = 1; s <= num; s ++) res = (res + f[n][ok[s]]) % mod;
	cout << res << '\n';
	
//	cout << num << '\n';
	
	return 0;
}
2024/8/18 13:43
加载中...