枚举k * k 的位置, 然后接上它周围白色连通块的数量, 再统计完全在k * k范围里的连通块, 这个只要某个连通块全部的方格
在k * k里面就好, 并且k * k是一行一行移的, 所以可以优化到n ^ 3。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 500 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); int n, k, idx, now, id[N][N], sum[N][N]; bool vis[N * N]; char Map[N][N]; int fa[N * N], cnt[N * N], num[N * N]; int getRoot(int x) { return fa[x] == x ? x : fa[x] = getRoot(fa[x]); } void change(int x, int op) { x = getRoot(x); if(op == 1) { num[x]--; if(!num[x]) now += cnt[x]; } else { if(!num[x]) now -= cnt[x]; num[x]++; } } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n * n; i++) fa[i] = i; for(int i = 1; i <= n; i++) scanf("%s", Map[i] + 1); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(Map[i][j] == '.') id[i][j] = ++idx, cnt[idx] = 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(Map[i][j] != '.') continue; if(Map[i - 1][j] == '.') { int x = getRoot(id[i][j]); int y = getRoot(id[i - 1][j]); if(x != y) fa[y] = x, cnt[x] += cnt[y]; } if(Map[i][j - 1] == '.') { int x = getRoot(id[i][j]); int y = getRoot(id[i][j - 1]); if(x != y) fa[y] = x, cnt[x] += cnt[y]; } } } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + (Map[i][j] == 'X'); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(Map[i][j] == '.') num[getRoot(id[i][j])]++; int ans = 0; queue<int> que; for(int i = 1; i + k - 1 <= n; i++) { for(int j = 1; j + k - 1 <= n; j++) { if(j == 1) { for(int u = i; u < i + k; u++) for(int v = j; v < j + k; v++) change(id[u][v], 1); } int ret = 0; if(i - 1 > 0) { for(int z = j; z <= j + k - 1; z++) { if(Map[i - 1][z] != '.') continue; int x = getRoot(id[i - 1][z]); if(!vis[x]) { vis[x] = true; que.push(x); ret += cnt[x]; } } } if(i + k <= n) { for(int z = j; z <= j + k - 1; z++) { if(Map[i + k][z] != '.') continue; int x = getRoot(id[i + k][z]); if(!vis[x]) { vis[x] = true; que.push(x); ret += cnt[x]; } } } if(j - 1 > 0) { for(int z = i; z <= i + k - 1; z++) { if(Map[z][j - 1] != '.') continue; int x = getRoot(id[z][j - 1]); if(!vis[x]) { vis[x] = true; que.push(x); ret += cnt[x]; } } } if(j + k <= n) { for(int z = i; z <= i + k - 1; z++) { if(Map[z][j + k] != '.') continue; int x = getRoot(id[z][j + k]); if(!vis[x]) { vis[x] = true; que.push(x); ret += cnt[x]; } } } while(!que.empty()) { vis[que.front()] = false; que.pop(); } ans = max(ans, now + ret + sum[i + k - 1][j + k - 1] - sum[i - 1][j + k - 1] - sum[i + k - 1][j - 1] + sum[i - 1][j - 1]); if(j + k <= n) { for(int z = i; z < i + k; z++) change(id[z][j], -1); for(int z = i; z < i + k; z++) change(id[z][j + k], 1); } else { for(int u = i; u < i + k; u++) for(int v = j; v < j + k; v++) change(id[u][v], -1); } } } printf("%d\n", ans); return 0; } /* */