[USACO11NOV]Binary Sudoku G 题解

定义一个 \(3\times3\) 的表格 \(a\),表示每个小九宫格内 1 的个数的奇偶状态。

再定义两个长为 \(9\) 的数组 \(c0,c1\),表示每行每列上 1 的个数的奇偶状态。

\(d_{i,j}\) 取反时,会将 \(a_{[\frac{i}{3}],[\frac{j}{3}]},c0_i,c1_j\) 各取反一次。

要将 \(a_{i,j}\) 全部变为 0,\(a\) 内 1 的个数是至少需要取反的次数。

\(c0,c1\) 各划分为三块,每三个数一块。

\(a_{i,j}\) 取反了,则 \(c0\) 的第 \(i\) 块中的某个数和 \(c1\) 的第 \(j\) 块中的某个数也会取反。

我们优先选择块中为 1 的取反,如果没有 1 就统一将块中的第一个数取反。

最终 \(a_{i,j}\) 全部变为 0 了,但是题目还要求将 \(c0_i\)\(c1_i\) 全部变为 0,可以证明,这时 \(c0\)\(c1\) 的每个块中只会有偶数个 1。所以这时候 \(c0\)\(c1\) 内 1 的个数的最大值就是要再取反的次数。

时间复杂度:输入的时间复杂度

代码:

#include<iostream>
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
int ans,num1,num2;
bool a[3][3],c0[9],c1[9];
char ch;
signed main(){
	rept(i,0,9)rept(j,0,9){
		cin>>ch;
		if(ch=='1'){
			a[i/3][j/3]^=1;
			c0[i]^=1,c1[j]^=1;
		}
	}
	rept(i,0,3)
		rept(j,0,3)if(a[i][j]){
			rept(k,i*3,i*3+3)if(c0[k]){
				c0[k]^=1;
				goto next1;
			}
			c0[i*3]^=1;
			next1:;
			rept(k,j*3,j*3+3)if(c1[k]){
				c1[k]^=1;
				goto next2;
			}
			c1[j*3]^=1;
			next2:;
			ans++;
		}
	rept(i,0,9)num1+=c0[i],num2+=c1[i];
	cout<<ans+max(num1,num2);
	return 0;
}
posted @ 2024-02-27 22:04  zifanwang  阅读(7)  评论(0编辑  收藏  举报