JZOJ 1389. 玩诈欺的小杉

思路

考虑一个点要不要翻,如果它左边的点为 (1),那么它必须翻
所以我们可以从左往右一列一列地翻
先枚举第 (0) 列的状态
然后之后的列就确定了
判断一下最后一列是不是 (0) 就行了
状压快速翻

(Code)

#include<cstdio>
#include<cstring>
using namespace std;

int n , m , t , b[21] , c[21];

int main()
{
	scanf("%d%d%d" , &n , &m , &t);
	char s[50];
	for(; t; t--)
	{
		memset(c , 0 , sizeof c);
		for(register int i = 1; i <= n; i++)
		{
			scanf("%s" , s);
			for(register int j = 0; j < m; j++)
				c[j + 1] = (c[j + 1] << 1) + s[j] - '0';
		}
		int up = (1 << n) - 1 , ans = 0;
		for(register int i = 0; i <= up; i++)
		{
			b[0] = i;
			for(register int j = 1; j <= m; j++) b[j] = c[j] & up;
			for(register int j = 1; j <= m; j++)
			{
				b[j] = b[j] ^ b[j - 1] ^ (b[j - 1] << 1) ^ (b[j - 1] << 2) ^ (b[j - 1] >> 1) ^ (b[j - 1] >> 2);
				b[j] &= up;
				b[j + 1] = (b[j + 1] ^ b[j - 1]) & up;
			}
			if (b[m] == 0) ans++;
		}
		printf("%d
" , ans);
	}
}
原文地址:https://www.cnblogs.com/leiyuanze/p/13470349.html