Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Do not start with BFS on the current # cells. You are allowed to add cells, so disconnected now does not mean impossible.
In any valid final shape, a black cell cannot have black neighbors on both left and right, or both up and down. That would instantly create three consecutive black cells.
So the connected black cells form a path/cycle where every internal cell turns . If the shape is larger than a block, it has to keep walking like a diagonal staircase.
A diagonal staircase fits inside two adjacent diagonals: either two adjacent values of , or two adjacent values of .
Track min/max of row, column, , and over all original black cells. The answer is YES iff they fit inside a rectangle, or two adjacent diagonals, or two adjacent diagonals.
The fake-hard part is connectivity. You might think we need to search for some custom way to connect all components. Nope. The final connected shape is extremely restricted.
Classifying valid shapes
Treat black cells as vertices of a graph, with edges between orthogonally adjacent black cells.
In a valid final grid, no cell can have black neighbors on both sides horizontally:
###That would be illegal. Same vertically.
So every black cell has degree at most . Also, if a cell has degree , the two edges must be perpendicular. A straight-through cell would again make three consecutive black cells.
That means any connected final shape is basically a path or a tiny cycle, and every internal step must turn.
Now look at a path of cells. Consecutive moves must alternate between horizontal and vertical. Suppose the path moves right, then vertically, then left. Those four cells form a block. After that, trying to continue either closes that exact block or creates three cells in one row/column. So a shape that is not contained in a block cannot reverse horizontal direction. By the same argument, it cannot reverse vertical direction either.
Therefore, any larger valid connected shape uses only two directions, like right+down, right+up, left+down, or left+up. That is exactly a diagonal staircase.
A staircase using right+down or left+up stays on two adjacent values of .
A staircase using right+up or left+down stays on two adjacent values of .
So every possible final shape is one of these three types:
Since the original black cells must be a subset of the final shape, they must fit one of those three cages. That gives necessity.
Why the checks are enough
If all black cells fit in a rectangle, paint that whole rectangle black. Connected, and no line of length .
If all black cells fit in two adjacent diagonals, paint the missing cells in that strip between the needed endpoints. It becomes a staircase like:
##..
.##.
..##Every row and every column has at most two black cells from the strip, and the strip is connected.
For two adjacent diagonals, it is the same picture mirrored:
..##
.##.
##..So the implementation just scans the original # cells and records ranges.
For black cells , compute:
Then answer YES if:
or
or
The empty grid is also YES, because we can paint any one cell black. With the usual infinity initialization, it falls out naturally.
Complexity is per test case and extra memory. Very small, very clean, no graph-search circus required.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
const int INF = 1e9;
int minR = INF, maxR = -INF;
int minC = INF, maxC = -INF;
int minSum = INF, maxSum = -INF;
int minDiff = INF, maxDiff = -INF;
for (int r = 0; r < n; r++) {
string s;
cin >> s;
for (int c = 0; c < n; c++) {
if (s[c] != '#') continue;
minR = min(minR, r);
maxR = max(maxR, r);
minC = min(minC, c);
maxC = max(maxC, c);
minSum = min(minSum, r + c);
maxSum = max(maxSum, r + c);
minDiff = min(minDiff, r - c);
maxDiff = max(maxDiff, r - c);
}
}
bool ok = false;
ok |= (maxR - minR <= 1 && maxC - minC <= 1);
ok |= (maxSum - minSum <= 1);
ok |= (maxDiff - minDiff <= 1);
cout << (ok ? "YES" : "NO") << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
const int INF = 1e9;
int minR = INF, maxR = -INF;
int minC = INF, maxC = -INF;
int minSum = INF, maxSum = -INF;
int minDiff = INF, maxDiff = -INF;
for (int r = 0; r < n; r++) {
string s;
cin >> s;
for (int c = 0; c < n; c++) {
if (s[c] != '#') continue;
minR = min(minR, r);
maxR = max(maxR, r);
minC = min(minC, c);
maxC = max(maxC, c);
minSum = min(minSum, r + c);
maxSum = max(maxSum, r + c);
minDiff = min(minDiff, r - c);
maxDiff = max(maxDiff, r - c);
}
}
bool ok = false;
ok |= (maxR - minR <= 1 && maxC - minC <= 1);
ok |= (maxSum - minSum <= 1);
ok |= (maxDiff - minDiff <= 1);
cout << (ok ? "YES" : "NO") << '\n';
}
}