E - Defect-free Squares Editorial by en_translator
Consider solving this problem with DP (Dynamic Programming). Define
- \(\mathrm{dp}[i][j] :=\) (the maximum side \(n\) of a holeless square whose bottom-right corner is \((i, j)\), or \(0\) if no such square exists).
(If \((i, j)\) is out of the range \(1 \leq i \leq H\) and \(1 \leq j \leq W\), then let \(\mathrm{dp}[i][j] = 0\).)
Then the answer to this problem is expressed using \(\mathrm{dp}[i][j]\) as:
\[\sum_{i=1}^H \sum_{j=1}^W \mathrm{dp}[i][j].\]
(Proof) Every holeless square has a unique bottom-right square. Also, if \(\mathrm{dp}[i][j] = k\), then the square of size \(n\) whose bottom-right square is \((i,j)\) is a holeless square for all \(n=1, 2, \dots, k\). Thus, every holeless squares are counted exactly once in the summation above. (End of proof)
- Roughly speaking, you can come up with the expression above as follows:
- We want to count all the holeless squares.
- This can be solved if we can count the number of holeless squares whose bottom-right square is \((i, j)\) for all squares \((i, j)\).
- Let’s solve the subproblem with DP!
So, the problem can be solved if \(\mathrm{dp}[i][j]\) is found for all \(1 \leq i \leq H\) and \(1 \leq j \leq W\).
With some observations, we obtain the following recurrence relations on \(\mathrm{dp}[\ast][\ast]\) as follows:
\[ \mathrm{dp}[i][j] = \begin{cases} \min\lbrace \mathrm{dp}[i-1][j], \mathrm{dp}[i][j-1], \mathrm{dp}[i-1][j-1] \rbrace + 1 & S[i][j] = \mathrm{o}\\ 0 & S[i][j] = \mathrm{x} \end{cases} \]
This is justified because, for all squares \((i, j)\) and positive integers \(n\), “1.” if and only if “2., 3., 4., and 5.”. (You may understand it by drawing a figure.)
- A square region of size \(n\) whose bottom-right square is \((i, j)\) is holeless.
- A square region of size \((n-1)\) whose bottom-right square is \((i, j-1)\) is holeless.
- A square region of size \((n-1)\) whose bottom-right square is \((i-1, j)\) is holeless.
- A square region of size \((n-1)\) whose bottom-right square is \((i-1, j)\) is holeless.
- \((i, j)\) is not holed.
Thus, it is sufficient to compute \(\mathrm{dp}[i][j]\) \((1 \leq i \leq H, 1 \leq j \leq W)\) in ascending order of \(i\), then in \(j\).
The complexity is \(\mathrm{O}(HW + N)\), which is fast enough.
- Sample code (C++)
#include <bits/stdc++.h>
using namespace std;
constexpr int nmax = 3030;
int hole[nmax][nmax];
int dp[nmax][nmax];
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int H, W, N;
cin >> H >> W >> N;
for (int i = 0, a, b; i < N; i++) {
cin >> a >> b, hole[a][b] = 1;
}
long long ans = 0;
for (int i = 1; i <= H; i++) {
for (int j = 1; j <= W; j++) {
if (hole[i][j]) continue;
dp[i][j] = min({dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]}) + 1;
ans += dp[i][j];
}
}
cout << ans << "\n";
}
posted:
last update: