Codeforces Round #578D矩阵前缀和DP

本文探讨了CFPaint软件中的一个算法问题,即通过使用特定大小的橡皮擦工具,如何在n*n的网格上实现最多数量的全白行或列。文章详细解析了解决方案的步骤,包括计算行和列中黑色单元格的数量,标记可能产生新全白行或列的单元格,以及利用动态规划思想确定最佳操作位置。

D. White Lines(画白线)

Gildong has bought a famous painting software cfpaint. The working screen of cfpaint is square-shaped consisting of nn rows and nncolumns of square cells. The rows are numbered from 11 to nn, from top to bottom, and the columns are numbered from 11 to nn, from left to right. The position of a cell at row rr and column cc is represented as (r,c)(r,c). There are only two colors for the cells in cfpaint — black and white.

There is a tool named eraser in cfpaint. The eraser has an integer size kk (1≤k≤n1≤k≤n). To use the eraser, Gildong needs to click on a cell (i,j)(i,j) where 1≤i,j≤n−k+11≤i,j≤n−k+1. When a cell (i,j)(i,j) is clicked, all of the cells (i′,j′)(i′,j′) where i≤i′≤i+k−1i≤i′≤i+k−1 and j≤j′≤j+k−1j≤j′≤j+k−1 become white. In other words, a square with side equal to kk cells and top left corner at (i,j)(i,j) is colored white.

A white line is a row or a column without any black cells.

Gildong has worked with cfpaint for some time, so some of the cells (possibly zero or all) are currently black. He wants to know the maximum number of white lines after using the eraser exactly once. Help Gildong find the answer to his question.

Input

The first line contains two integers nn and kk (1≤k≤n≤20001≤k≤n≤2000) — the number of rows and columns, and the size of the eraser.

The next nn lines contain nn characters each without spaces. The jj-th character in the ii-th line represents the cell at (i,j)(i,j). Each character is given as either 'B' representing a black cell, or 'W' representing a white cell.

Output

Print one integer: the maximum number of white lines after using the eraser exactly once.

input

4 2
BWWW
WBBW
WBBW
WWWB

Output

4

链接:https://codeforces.com/contest/1200/problem/D

题意:n*n的矩阵中,将一个k*k的矩阵内字母全变为W,求一次操作,横列全为W线最多有几条。

题解:先计算行、列前缀和有多少个B,//arr[2005][2005];

其次标记修改以【i,j】为首的行、列是否产生新w线,//book[2005][2005];

计算标记的w线数量前缀和,//opt[2005][2005];

用dp思想求以【i,j】为头的k*k最多白线

样例n=5,k=3,答案为2
BWBBB
BWBBB
BBBBB
BBBBB
WBBBW
book[2005][2005] ( 以[i,j]为头的(行x,列y)是否能够产生新w线)
0,00,00,00,00,0
0,00,00,00,00,0
0,00,10,00,00,0
0,00,00,00,00,0
0,01,00,00,00,0
opt[2005][2005](新W线段个数前缀和opt)
0,00,00,00,00,0
0,00,00,00,00,0
0,01,01,01,01,0
0,00,00,00,00,0
0,00,10,00,00,0
#include<iostream>
#include<cstring>
using namespace std; 
struct node
{
	int x,y;
};
node book[2005][2005];
node opt[2005][2005];
node arr[2005][2005];//横、纵 B的个数前缀和 
int n,k;
void solve()
{
	int num=0;		//不做修改前白线数量 
	for(int i=1;i<=n;i++)
	{
		if(arr[i][n].x==0)
		num++;
	}
	for(int j=1;j<=n;j++)
	{
		if(arr[n][j].y==0)
		num++;
	}
	for(int i=1;i<=n;i++)//横向行可全变W标记 
	{
		for(int j=1;j<=n-k+1;j++)
		{
			if(arr[i][n].x!=0)
			{
				if(arr[i][j+k-1].x-arr[i][j-1].x==arr[i][n].x)
				{
					book[i][j].x=1;
				}
			}
		}
	}
	for(int j=1;j<=n;j++)//纵向列 可全变W标记 
	{
		for(int i=1;i<=n-k+1;i++)
		{
			if(arr[n][j].y!=0)
			{
				if(arr[i+k-1][j].y-arr[i-1][j].y==arr[n][j].y)
				{
					book[i][j].y=1;
				}
			}
		}
	}

	for(int i=1;i<=n;i++)//opt前缀和 
	{
		for(int j=1;j<=n;j++)
		{
			opt[i][j].x=opt[i][j-1].x+book[i][j].y;
			opt[i][j].y=opt[i-1][j].y+book[i][j].x;
		}
	}
	int tempnum=0;
	for(int i=1;i<=n-k+1;i++)
	{
		for(int j=1;j<=n-k+1;j++)
		{
		tempnum=max(tempnum,opt[i+k-1][j].y-opt[i-1][j].y+opt[i][j+k-1].x-opt[i][j-1].x);
		}
	}
	printf("%d\n",num+tempnum);
}
int main()
{
	string s[2005];
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		s[i]="0"+s[i];
		for(int j=1;j<=n;j++)//横、纵 B的个数前缀和 
		{
			if(s[i][j]=='B')
			{
				arr[i][j].x=arr[i][j-1].x+1;
				arr[i][j].y=arr[i-1][j].y+1;
			}
			else
			{
				arr[i][j].x=arr[i][j-1].x;
				arr[i][j].y=arr[i-1][j].y;
			}
		}
	}
	solve();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值