G - Flip Row or Col Editorial by en_translator
When columns to perform operations are fixed, we can independently minimize the sum of the numbers written on each row. If a row contains \(c_0\) zeros and \(c_1\) ones, it is optimal to do nothing on it if \(c_0\geq c_1\) and perform an operation on it if \(c_0\lt c_1\). This way, the row will have \(\min(c_0,c_1)=\min(c_1,W-c_1)\) ones.
Regard the binary string in each row as a binary integer. Let \(B_i\) be \(\sum_{j=0}^{W-1}A_{i,j}2^j\). Representing by \(X\) the fixed set of operations against columns, we find that\(\min \sum A_{x,y}\) equals \(\sum_{i=0}^{H-1}\min(\mathrm{popcount}(B_i\oplus X),W-\mathrm{popcount}(B_i\oplus X))\) by the discussion above (where \(\mathrm{popcount}\) is the number of ones in the binary representation, and \(\oplus\) denotes bitwise XOR (exclusive logical sum)). Since \(X\) can take between \(0\) and \(2^W-1\), the sought value is \(\displaystyle\min_{0\leq X\lt 2^W}\sum_{i=0}^{H-1}\min(\mathrm{popcount}(B_i\oplus X),W-\mathrm{popcount}(B_i \oplus X))\).
Consider evaluating \(\sum_{i=0}^{H-1}\min(\mathrm{popcount}(B_i\oplus X),W-\mathrm{popcount}(B_i \oplus X))\) for each \(X=0,1,\ldots,2^W-1\). This can be done by counting the number of indices \(i\) with\(B_i\oplus X=j\) for each \(j=0,1,\ldots,W\). We use bit DP (Dynamic Programming) to find it. Define \(dp[X][j][c] (0\leq X\lt 2^W,0\leq j,c\leq W)\) by:
- the number of indices \(i\) such that \(B_i\) is one of \(X\oplus 0,X\oplus 1,\ldots,X\oplus (2^j-1)\), and \(X\) and \(B_i\) differ exactly at \(c\) bits.
The transitions are as follows:
- \(dp[X][j+1][c]+= dp[X][j][c]\),
- \(dp[X][j+1][c+1]+= dp[X\oplus 2^j][j][c]\).
Then, \(\sum_{i=0}^{H-1}\min(\mathrm{popcount}(B_i\oplus X),W-\mathrm{popcount}(B_i \oplus X))=\sum_{c=0}^W dp[X][W][c]\times \min(c,W-c)\).
The time complexity is \(O(HW+2^WW^2)\), and the spacial complexity is \(O(W^22^W)\) or \(O(W2^W)\).
H, W = map(int, input().split())
dp = [[0] * (1 << W) for i in range(W + 1)]
for i in range(H):
dp[0][int(input(), 2)] += 1
for i in range(W):
for j in range(i, -1, -1):
for bit in range(1 << W):
dp[j + 1][bit ^ (1 << i)] += dp[j][bit]
ans = 1 << 60
for bit in range(1 << W):
res = 0
for i in range(W + 1):
res += min(i, W - i) * dp[i][bit]
ans = min(ans, res)
print(ans)
posted:
last update: