1. 程式人生 > 實用技巧 >JZOJ 1389. 玩詐欺的小杉

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\n" , ans);
	}
}