D. White Lines(预处理,前缀和)

纯暴力很容易想

( ) B ( ) B 预处理每行每列最左(上)的B和最右(下)的B

O ( n 2 ) , O ( n ) , 然后O(n^2)枚举每个点作为正方形左上角,O(n)判断,显然超时。

暴力T上天的代码

考虑如何O(1)判断每个点的贡献

s u m 1 [ i ] [ j ] i [ j , j + k 1 ] 线 预处理sum1[i][j]表示前i行覆盖[j,j+k-1]列的格子产生的白线

s u m 2 [ i ] [ j ] j [ i , i + k 1 ] 线 预处理sum2[i][j]表示前j列覆盖[i,i+k-1]行的格子产生的白线

i , j , 那么以i,j为左上角,贡献就是

s u m 1 [ i + k 1 ] [ j ] s u m 1 [ i 1 ] [ j ] + s u m 2 [ j + k 1 ] [ i ] s u m 2 [ j 1 ] [ i ] sum1[i+k-1][j]-sum1[i-1][j]+sum2[j+k-1][i]-sum2[j-1][i]

#include <bits/stdc++.h>
using namespace std;
const int maxn=2009;
int r[maxn][maxn],d[maxn][maxn],n,k;
int sum1[maxn][maxn],sum2[maxn][maxn];
char s[maxn][maxn];
int main()
{
	cin >> 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');
		d[j][i]=d[j][i-1]+(s[i][j]=='B');
	}
	int tot=0,ans=0;
	for(int i=1;i<=n;i++){
		if(r[i][n]==0) tot++;
		if(d[i][n]==0) tot++;
	}
	for(int i=1;i<=n;i++)
	for(int j=1;j+k-1<=n;j++)
	{
		//第j到j+k-1个字母被覆盖 
		sum1[i][j]=sum1[i-1][j]+( r[i][j+k-1]-r[i][j-1]==r[i][n]&&r[i][n]!=0 );
		sum2[i][j]=sum2[i-1][j]+( d[i][j+k-1]-d[i][j-1]==d[i][n]&&d[i][n]!=0 );
	}
	for(int i=1;i<=n-k+1;i++)
	for(int j=1;j<=n-k+1;j++)
		ans=max(ans, tot+sum1[i+k-1][j]-sum1[i-1][j]+sum2[j+k-1][i]-sum2[j-1][i]);
	cout << ans;
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107731449