「JOI 2018 Final」糰子製作
阿新 • • 發佈:2020-11-20
一個糰子可能被從兩個方向選取,但只能保留一個方向,相同取向的方案之間不會影響,這形成了個二分圖,在不能同時選的方案之間連邊,
答案就是最大獨立集,但邊數太多,會 \(T\)。但很多方案之間是獨立的,確切來說只有中間點在同一斜線上的方案才可能矛盾,
於是可以對每個斜線上進行 \(dp\) 即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i = (a); i <= (b); i++) #define per(i, a, b) for (int i = (a); i >= (b); i--) #define fi first #define se second const int N = 3005, inf = 0x3f3f3f3f, mod = 1e9 + 7; typedef pair <int, int> P; typedef long long LL; int n, m, ans, f[N][3]; char a[N][N]; bool chk_(int x, int y, int op) { if (op == 1) return a[x][y + 1] == 'W' && a[x][y - 1] == 'R'; else return a[x - 1][y] == 'R' && a[x + 1][y] == 'W'; } int main() { // freopen("data.in", "r", stdin); scanf("%d%d", &n, &m); rep (i, 1, n) scanf("%s", a[i] + 1); rep (xy, 2, n + m) { int lx = max(1, xy - m), rx = min(xy, n); f[lx - 1][0] = 0, f[lx - 1][1] = f[lx - 1][2] = -inf; rep (x, lx, rx) { int y = xy - x; f[x][0] = max(f[x - 1][0], max(f[x - 1][1], f[x - 1][2])), f[x][1] = f[x][2] = -inf; if (a[x][y] != 'G') continue; if (chk_(x, y, 1)) f[x][1] = max(f[x - 1][1], f[x - 1][0]) + 1; if (chk_(x, y, 2)) f[x][2] = max(f[x - 1][2], f[x - 1][0]) + 1; } ans += max(f[rx][0], max(f[rx][1], f[rx][2])); } printf("%d\n", ans); return 0; }