CF1200D White Lines | 前缀和
Examples
input 1
4 2 BWWW WBBW WBBW WWWB
output 1
4
input 2
3 1 BWB WWB BWB
output 2
2
input 3
5 3 BWBBB BWBBB BBBBB BBBBB WBBBW
output 3
2
input 4
2 2 BW WB
output 4
4
input 5
2 1 WW WW
output 5
4
Note
In the first example, Gildong can click the cell(2,2), then the working screen becomes:
BWWW
WWWW
WWWW
WWWB
Then there are four white lines — the 2-nd and 3-rd row, and the 2-nd and 3-rd column.
In the second example, clicking the cell (2,3)makes the 2-nd row a white line.
In the third example, both the 2-nd column and 5-th row become white lines by clicking the cell (3,2).
题意:有一个n*n的格子,由'B'和'W'组成,B代表黑色,W代表白色。现在有一个k*k的橡皮擦,你可以选一个地方(i,j)(1≤i≤n-k+1,1≤j≤n-k+1)点击,它会将(i',j')(i≤i'≤i+k-1,j≤j'≤j+k-1)区域全部变为白色,若一行(列)全是W全是W那么这一行(列)就是一条白色的线。现在问你擦一次之后最多能有多少条线。
题解:我们可以利用前缀和统计每一行每一列有多少个黑格子,前缀和为0表示这一行(列)本来就是一条白线,可以算出初始白线的数量。然后我们一行行一列列判断从这个点开始往右(下)k个变成白色之后会不会增加一条线,再用前缀和记录前n行(列)一共能加几条线。最后枚举每一个可以点击的点看这个区间能增加多少白线更新ans。
代码:
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 2e3 + 10; char s[N][N]; int r[N][N],c[N][N],rr[N][N],cc[N][N]; int main(){ int n,k; scanf("%d%d",&n,&k); for (int i = 1; i <= n; i++) scanf("%s",s[i]+1); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { r[i][j] = r[i][j-1]+(s[i][j]=='B'); c[i][j] = c[i][j-1]+(s[j][i]=='B'); } } int tot = 0; for (int i = 1; i <= n; i++) tot+=(r[i][n] == 0) + (c[i][n] == 0); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n-k+1; j++) { rr[i][j] = rr[i-1][j] + (r[i][j+k-1] - r[i][j-1] == r[i][n] && r[i][n]); cc[i][j] = cc[i-1][j] + (c[i][j+k-1] - c[i][j-1] == c[i][n] && c[i][n]); } } int ans = tot; for (int i = 1; i <= n-k+1; i++) for (int j = 1; j <= n-k+1; j++) ans = max(ans,tot+rr[i+k-1][j]-rr[i-1][j]+cc[j+k-1][i]-cc[j-1][i]); printf("%d\n", ans); return 0; }