> Description
KXT是一个很无聊的小朋友,一天到晚都在打坐…
一天,被他发现了一个比打坐更无聊的事情——打砖块。很多块砖分布在一个mm的矩阵中,他可以消掉以他为左上角顶点的一个nn的矩阵里的所有砖块。
喜欢偷懒的他请来了你帮他计算可以消掉最多的砖块数(只能消一次)。
> Input
第一行:用空格隔开的三个整数n、m、k。
接下来k行,每行2个用空格隔开的整数Xi、Yi,表示第i块砖在Xi行、Yi列的位置。
> Output
为可以消掉最多的砖块数。
> Sample Input
5 10 11
2 1
4 6
4 9
3 9
9 7
9 9
7 9
8 10
8 8
8 6
10 2
> Sample Output
6
> Hink
【数据范围】
n<=m; k<=m*m
60%:n<=70; m<=70; k<=4900
100%:n<=1000; m<=1000; k<=1000000;
> 解题思路
求前缀和都会,就是它有固定的子矩阵边长,其实也就是把循环和计算那里改一下就行了。
> 代码
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1001;
int n,m,k,x,y,len[maxn][maxn]={0},ans;
int main()
{
int sum;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
len[x][y]=1;
}
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
len[i][j]+=len[i-1][j];
//计算前缀和
for(int i=1;i<=m-n+1;i++)
for(int j=1;j<=m-n+1;j++)
{
sum=0;
for(int k=j;k<=j+n-1;k++)
sum+=len[i+n-1][k]-len[i-1][k];
//先累加,再判断
if(sum>ans) ans=sum;
}
printf("%d",ans);
return 0;
}