#include <bits/stdc++.h>
#define bp __builtin_popcountll
#define pb push_back
#define in(s) freopen(s, "r", stdin);
#define out(s) freopen(s, "w", stdout);
#define inout(s, end1, end2) freopen((string(s) + "." + end1).c_str(), "r", stdin),\
freopen((string(s) + "." + end2).c_str(), "w", stdout);
#define fi first
#define se second
#define bw(i, r, l) for (int i = r - 1; i >= l; i--)
#define fw(i, l, r) for (int i = l; i < r; i++)
#define fa(i, x) for (auto i: x)
using namespace std;
const int mod = 1e9 + 7, inf = 1061109567;
const long long infll = 4557430888798830399;
const int N = 3005;
int n, m, ans = 0, idHorizontal[N][N], idVertical[N][N], pos = 0, mnRow[N], mxRow[N], dp[N][8];
int mnCol[N], mxCol[N];
char a[N][N];
int p[N * N], sz[N * N], row[N * N], col[N * N]; //Maximally 6 million DSU
bool dir[N * N];
vector<int> inDSU[N * N];
bool check(int i, int j, string pattern) {
if (i < 0 || i >= n || j + pattern.length() - 1 >= m || j < 0) return false;
fw (k, 0, pattern.length()) {
if (a[i][j + k] != pattern[k]) return false;
}
return true;
}
int getp(int u) {
return u == p[u] ? u : p[u] = getp(p[u]);
}
void joint(int u, int v) {
u = getp(u), v = getp(v);
if (u == v) return;
if (sz[u] < sz[v]) swap(u, v);
sz[u] += sz[v];
p[v] = u;
}
int getRowLength(int row) {
return mxCol[row] - mnCol[row] + 1;
}
int getColLength(int col) {
return mxRow[col] - mnRow[col] + 1;
}
bool checkMasks(int curMask, int prvMask, int curMaskLen, int prvMaskLen, int diff) {
//diff represents mnRow[prvColumn] - mnRow[curColumn]
//All meeting rows must be the same status (picked or not picked)
fw (i, diff, min(curMaskLen, prvMaskLen) + diff) {
int curBit = (curMask & (1 << i)), prvBit = (prvMask & (1 << (i - diff)));
if (curBit != prvBit) return false;
}
return true;
}
int getExtraRows(int mask, int col, int diff) {
int ans = 0;
fw (i, 0, min(diff, 3)) if (mask & (1 << i)) {
if (getRowLength(mnRow[col] + i) < 3) return -1;
ans++;
}
return ans;
}
signed main() {
#ifdef BLU
in("blu.inp");
// out("out1.out");
#endif
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
fw (i, 0, n) fw (j, 0, m) cin >> a[i][j];
memset(idHorizontal, -1, sizeof idHorizontal);
memset(idVertical, -1, sizeof idVertical);
fw (i, 0, n) {
fw (j, 0, m) {
// cout << "i = " << i << " j = " << j << " pos = " << pos << "\n";
if (check(i, j, "RGW")) {
idHorizontal[i][j] = pos;
row[pos] = i, col[pos] = j;
dir[pos] = 0;
pos++;
}
if (check(i, j, "R") && check(i + 1, j, "G") && check(i + 2, j, "W")) {
idVertical[i][j] = pos;
row[pos] = i, col[pos] = j;
dir[pos] = 1;
pos++;
}
}
}
fw (i, 0, pos) p[i] = i, sz[i] = 1;
fw (i, 0, n) fw (j, 0, m) {
if (check(i, j, "RGW")) {
if (check(i + 1, j, "G") && check(i + 2, j, "W"))
joint(idHorizontal[i][j], idVertical[i][j]);
if (check(i - 1, j + 1, "R") && check(i + 1, j + 1, "W"))
joint(idHorizontal[i][j], idVertical[i - 1][j + 1]);
if (check(i - 2, j + 2, "R") && check(i - 1, j + 2, "G"))
joint(idHorizontal[i][j], idVertical[i - 2][j + 2]);
}
}
//Use dp on each DSU and solve them separately.
fw (i, 0, pos) inDSU[getp(i)].pb(i);
fw (i, 0, m) mnRow[i] = inf, mxRow[i] = -1;
fw (i, 0, n) mnCol[i] = inf, mxCol[i] = -1;
fw (i, 0, pos) if (getp(i) == i) {
int mnColumn = inf, mxColumn = -1, minRow = inf, maxRow = -1;
// cout << "DSU of " << i << "\n";
fa (j, inDSU[i]) {
// cout << row[j] + 1 << " " << col[j] + 1 << " " << (dir[j] ? "Vertical" : "Horizontal") << "\n";
if (dir[j] == 0) {
//Horizontal
mnColumn = min(mnColumn, col[j]);
mxColumn = max(mxColumn, col[j] + 2);
minRow = min(minRow, row[j]);
maxRow = max(maxRow, row[j]);
mnRow[col[j]] = min(mnRow[col[j]], row[j]);
mnRow[col[j] + 1] = min(mnRow[col[j] + 1], row[j]);
mnRow[col[j] + 2] = min(mnRow[col[j] + 2], row[j]);
mxRow[col[j]] = max(mxRow[col[j]], row[j]);
mxRow[col[j] + 1] = max(mxRow[col[j] + 1], row[j]);
mxRow[col[j] + 2] = max(mxRow[col[j] + 2], row[j]);
mnCol[row[j]] = min(mnCol[row[j]], col[j]);
mxCol[row[j]] = max(mxCol[row[j]], col[j] + 2);
} else {
//Vertical
mnColumn = min(mnColumn, col[j]);
mxColumn = max(mxColumn, col[j]);
minRow = min(minRow, row[j]);
maxRow = max(maxRow, row[j] + 2);
mnRow[col[j]] = min(mnRow[col[j]], row[j]);
mxRow[col[j]] = max(mxRow[col[j]], row[j] + 2);
mnCol[row[j]] = min(mnCol[row[j]], col[j]);
mnCol[row[j] + 1] = min(mnCol[row[j] + 1], col[j]);
mnCol[row[j] + 2] = min(mnCol[row[j] + 2], col[j]);
mxCol[row[j]] = max(mxCol[row[j]], row[j]);
mxCol[row[j] + 1] = max(mxCol[row[j] + 1], col[j]);
mxCol[row[j] + 2] = max(mxCol[row[j] + 2], col[j]);
}
}
// cout << "mnCol = " << mnColumn << " mxCol = " << mxColumn << "\n";
// fw (j, minRow, maxRow + 1) {
// cout << "row " << j + 1 << " mnCol = " << mnCol[j] + 1 << " mxCol = " << mxCol[j] + 1 << "\n";
// }
fw (j, mnColumn, mxColumn + 1) {
// cout << "col " << j + 1 << " mnRow = " << mnRow[j] + 1 << " mxRow = " << mxRow[j] + 1 << "\n";
int colLen = getColLength(j);
fw (mask, 0, (1 << colLen)) {
//ith bit of mask represents a[mnRow[j] + i][j]
dp[j][mask] = 0;
if (j > mnColumn) {
int prvColLen = getColLength(j - 1), diff = mnRow[j - 1] - mnRow[j];
int extraRows = getExtraRows(mask, j, diff);
if (extraRows == -1) continue; //Invalid mask (Picking non - RGW rows)
fw (prvMask, 0, (1 << prvColLen)) {
if (checkMasks(mask, prvMask, colLen, prvColLen, diff)) {
dp[j][mask] = max(dp[j][mask], dp[j - 1][prvMask] + extraRows);
}
}
} else {
int extraRows = getExtraRows(mask, j, inf);
if (extraRows == -1) continue;
dp[j][mask] = extraRows;
}
if (colLen == 3 && mask == 0) dp[j][mask]++; //Pick column
}
}
// fw (j, mnColumn, mxColumn + 1) fw (mask, 0, 8) if (dp[j][mask]) {
// cout << "Dp[" << j + 1 << "][" << mask << "] = " << dp[j][mask] << "\n";
// }
int dsuAns = 0;
fw (mask, 0, 8) dsuAns = max(dsuAns, dp[mxColumn][mask]);
fw (j, mnColumn, mxColumn + 1) {
mnRow[j] = inf;
mxRow[j] = -1;
}
fw (j, minRow, maxRow + 1) {
mnCol[j] = inf;
mxCol[j] = -1;
}
ans += dsuAns;
}
cout << ans;
return 0;
}
Compilation message
dango_maker.cpp: In function 'bool check(int, int, std::__cxx11::string)':
dango_maker.cpp:24:50: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
if (i < 0 || i >= n || j + pattern.length() - 1 >= m || j < 0) return false;
~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
dango_maker.cpp:11:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
#define fw(i, l, r) for (int i = l; i < r; i++)
dango_maker.cpp:25:6:
fw (k, 0, pattern.length()) {
~~~~~~~~~~~~~~~~~~~~~~
dango_maker.cpp:25:2: note: in expansion of macro 'fw'
fw (k, 0, pattern.length()) {
^~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Runtime error |
221 ms |
262148 KB |
Execution killed with signal 9 (could be triggered by violating memory limits) |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Runtime error |
221 ms |
262148 KB |
Execution killed with signal 9 (could be triggered by violating memory limits) |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Runtime error |
221 ms |
262148 KB |
Execution killed with signal 9 (could be triggered by violating memory limits) |
2 |
Halted |
0 ms |
0 KB |
- |