【动态规划】打砖块

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ssllyf/article/details/82959413

打砖块

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

Hint

【样例解释】  

站在第4行、6列的位置,可以消除6个方块。

【数据范围】

n<=m; k<=m*m

60%:n<=70; m<=70; k<=4900

100%:n<=1000; m<=1000; k<=1000000;

解题思路

枚举正方形中左上角的点,因为不存在负数,右下角的点就是s[i+n-1][j+n-1],在按照状态转移方程做出此题

s [ i ] [ j ] = s [ i 1 ] [ j ] + s [ i ] [ j 1 ] s [ i 1 ] [ j 1 ] + s [ i ] [ j ] s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+s[i][j]
a n s = m a x ( a n s , s [ i + n 1 ] [ j + n 1 ] s [ i + n 1 ] [ j 1 ] s [ i 1 ] [ j + n 1 ] + s [ i 1 ] [ j 1 ] ) ans=max(ans,s[i+n-1][j+n-1]-s[i+n-1][j-1]-s[i-1][j+n-1]+s[i-1][j-1])

#include<cstdio>
#include<iostream>
using namespace std;
int n,m,k,ans,x,y,s[1003][1003];
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=k;i++)
	  {
	  	scanf("%d%d",&x,&y);
	  	s[x][y]++;
	  }
	for (int i=1;i<=m;i++)
	  for (int j=1;j<=m;j++)
	    s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+s[i][j];//求出前缀和
	for (int i=1;i<=m-n+1;i++)
	  for (int j=1;j<=m-n+1;j++)
	    ans=max(ans,s[i+n-1][j+n-1]-s[i+n-1][j-1]-s[i-1][j+n-1]+s[i-1][j-1]);//计算当前面积
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/ssllyf/article/details/82959413