Official

D - 2x2 Erasing 2 Editorial by en_translator


This problem can be solved with several solutions.

  • Use a bit DP (dynamic programming) to scan the grid from the top row to bottom while managing the state of the cells within the last row.
  • Use a bit DP to scan the grid in lexicographical order of the cell indices \((i,j)\), while maintaining the state within the last \((W+1)\) cells.
  • Exploit the property that the answer to the problem is at most \(9\) (*) and perform brute-force search with pruning.

(*): If cells \((i,j)\) are painted white for all pairs of even numbers with \(1\leq i\leq H\) and \(1\leq j\leq W\), the condition is satisfied regardless of the state of the other cells. Under the constraints of the problem \(H,W\leq 7\), there are no more than \(9\) such cells, and the number of cells that need repainting to reach such state is also \(9\). Thus, there exists a way to satisfy the condition by repainting \(9\) or less cells, and the minimum number of cells required to repaint is at most \(9\).

Here, we only introduce the solution.
Let us define the state of row \(i\) \((1\leq i\leq H)\) as \(x_{i,1}+2\cdot x_{i,2}+2^2\cdot x_{i,3}+\cdots+2^{W-1}\cdot x_{i,W}\), where \(x_{i,j}\) \((1\leq j\leq W)\) is \(0\) if cell \((i,j)\) is painted white and \(1\) if it is black. Then, any row state is represented by an integer between \(0\) and \(2^W-1\).

Now, define \(dp[i][j]\) \((1\leq i\leq N,0\leq j\leq 2^W-1)\) as the minimum black cells needed to repaint in white to satisfy the following two conditions (or \(+\infty\) if there is no way):

  • The topmost \(i\) rows of the repainted grid does not have \(2\times 2\) all-black square region.
  • The state of the \(i\)-th row is \(j\).

First we consider \(dp[1][j]\). Since the second condition is automatically satisfied, it is sufficient to consider the first condition. If state \(j\) can be obtained from the initial state of row \(1\) by repainting some black cells in white, then \(dp[1][j]\) is the number of cells needed to repaint; otherwise, it is \(+\infty\).

Next, assume that we have found \(dp[i][j']\) for all \(0\leq j'<2^W\) and now want to find \(dp[i+1][j]\). First of all, if state \(j\) cannot be obtained from the initial state of row \((i+1)\) by repainting some black cells in white, then \(dp[1][j]\) is \(+\infty\). Otherwise, let \(S\) be the set of states \(j'\) of row \(i\) such that, when row \(i\) is in state \(j'\) and row \((i+1)\) in state \(j\), these rows do not contain a \(2\times 2\) all-black region. Then we have \(\displaystyle dp[i+1][j]=\min_{j'\in S}dp[i][j']+x\), where \(x\) is the number of cells required to be repainted to make row \((i+1)\)’s state \(j\).
Here, by definition of \(dp[i][j']\) and \(S\), note that one can perform exactly \(dp[i][j']+x\) operations so that the first \((i+1)\) rows do not contain a \(2\times 2\) all-black region, and so that the state of \(i\)-th and \((i+1)\)-th rows are \(j'\) and \(j\), respectively. Also note that this is the minimum operation count required to do so. By taking the minimum value over all possible states for the \(i\)-th row, the value satisfying the definition of \(dp[i+1][j]\) can be found.

The answer can be found as \(\displaystyle\min_{0\leq j<2^W} dp[N][j]\).

Let us analyze the complexity: since the \(dp\) array has \(H\cdot 2^W\) elements, and updating an element requires taking the minimum of up to \(2^W\) values, so it costs \(O(H\cdot 4^W)\) time per test case. Therefore, the overall time complexity is \(O(TH\cdot 4^W)\); since \(TH\cdot 4^W\leq 100\cdot 7\cdot2^{14}\sim 10^7\), this is fast enough under the constraints of the problem.
Therefore, the problem has been solved.

The second solution allows us to solve in an even faster \(O(THW\cdot 2^W)\) time.

Sample code in C++:

#include <bits/stdc++.h>
using namespace std;

#define INF (int)1e+9
#define rep(i, n) for(int i = 0; i < n; ++i)

int main(void){
	int t;
	cin>>t;
	rep(_,t){
		int h,w,k;
		cin>>h>>w;
		k=1<<w;

		vector<string>s(h);
		rep(i,h)cin>>s[i];

		vector<vector<bool> >allow(k,vector<bool>(k,true));
		rep(i,k){
			rep(j,k){
				rep(ii,w-1){
					if((((i>>ii)&3)==3)&&(((j>>ii)&3)==3)){
						allow[i][j]=false;
						break;
					}
				}
			}
		}

		vector<int>dp(k,INF);
		dp[0]=0;
		rep(i,h){
			int state=0;
			rep(j,w)if(s[i][j]=='#')state+=(1<<j);
			vector<int>dp2(k,INF);
			rep(j,k){
				if((j|state)==state){
					rep(jj,k){
						if(allow[jj][j])dp2[j]=min(dp2[j],dp[jj]+std::popcount(((unsigned int)(j^state))));
					}
				}
			}
			dp=dp2;
		}

		int ans=INF;
		rep(i,k)ans=min(ans,dp[i]);
		cout<<ans<<endl;
	}
	
	return 0;
}

posted:
last update: