【DP】 打砖块

题目

KXT是一个很无聊的小朋友,一天到晚都在打坐…
  一天,被他发现了一个比打坐更无聊的事情——打砖块。很多块砖分布在一个mm的矩阵中,他可以消掉以他为左上角顶点的一个nn的矩阵里的所有砖块。
  喜欢偷懒的他请来了你帮他计算可以消掉最多的砖块数(只能消一次)。

输入

第一行:用空格隔开的三个整数n、m、k。
  接下来k行,每行2个用空格隔开的整数Xi、Yi,表示第i块砖在Xi行、Yi列的位置。

输出

为可以消掉最多的砖块数。

输入输出样例

输入

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

输出

6

样例解释

【DP】 打砖块_第1张图片
站在第4行、6列的位置,可以消除6个方块。

数据范围

n<=m; k<=m*m 
60%:n<=70; m<=70; k<=4900 
100%:n<=1000; m<=1000; k<=1000000   

解题思路

这道题与求最大子矩阵之和很像,只不过是多了一个边长限制,那么只需要在计算及循环上做一下改动就可以了。

代码

#include
#include
using namespace std;
int m,k,n,a[1001][1001],maxn=0;
int main()
{
	int x,y;
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=k;i++)
	  scanf("%d%d",&x,&y),a[x][y]=1;//读入,每读入一个就在相应位置标记一下
	for (int i=1;i<=m;i++)
     for (int j=1;j<=m;j++
	 )
      a[i][j]+=a[i-1][j];//计算前缀和
	for (int i=1;i<=m-n+1;i++)//m-n+1为最大边界,过了m-n+1就超界了,求出来的答案也不正确了,不要忘了-1(重点!!!)
	 for (int j=1;j<=m-n+1;j++) 
	  {
	  	int sum=0;//清0
	  	for (int k=j;k<=j+n-1;k++)//(重点!)j+n-1为界限,不要忘了-1
	  	 {
	  	 	sum+=a[i+n-1][k]-a[i-1][k];//计算子矩阵中每一列的前缀和并加起来
	  	 	if (sum>maxn) maxn=sum;//求最大值
		   }
	  }
	  printf("%d",maxn);
} 

你可能感兴趣的:(DP)