欢乐赛C

HDU1559
原题链接https://vjudge.net/contest/350953#problem/C
在这里插入图片描述
在m,n的矩阵中找一个最大的x,y矩阵
本题需要用二维前缀和来写,一维前缀和用于计算a-b之间的数
二位前缀和则是用于计算(a,b)-(x,y)之间的数,
首先对于二维前缀和的计算方法
1 2 3
4 5 6
7 8 9
对于这个二维数组而言 1就是1 ,
2 是1 和2 的和;
3为1 2 3 的和
4 为1 4 的和;
5为1 2 4 5的和;
6 为1 2 3 4 5 6的和
7为1 4 7 的和
8为1 2 4 5 7 8;
9为 1 2 3 4 5 6 7 8 9
当然计算前缀和时也会有一点问题,我们是从左向右一排一排遍历,这样就无法计算类似1 2 4 5这样的数,通过图形可以发现一些公式,1 2 4 5是1 2加上1 4 再减去1(1 2和1 4 一共加了两次1所以要减去一个)再加上5当前的数。
通过这个我们可以发现 a[i][j]就是(0,0)和(i,j)组成的矩形的全部数的和
对于二维前缀和需要有一点变化,
假如我们需要计算5 6 8 9这个2*2的值,我们现在已知的是1 2 3 4 5 6 7 8 9的和以及1 2 3 和1 4 7 6,对于图形观察5-9我们可以通过1-9减去1-3再减去1-7来计算但是同时我们会发现1这个位置的数减去了两次所以我们还要加上多减去的一个1;
公式就出来了:a[9]-a[3]-a[7]+a[1];

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
long long map[1005][1005];
long long sum[1005][1005];
int main()
{
	long long t;
	scanf("%lld",&t);
	while(t--)
	{
		long long m,n,x,y;
		scanf("%lld %lld %lld %lld",&n,&m,&x,&y);
		memset(sum,0,sizeof(sum));
		memset(map,0,sizeof(map));
		long long i,j,maxx1=-1;;
		for(i=1; i<=n; i++)
		{
			for(j=1; j<=m; j++)
			{
				scanf("%lld",&map[i][j]);
				if(map[i][j]>=maxx1)//对于需要选取1*1的方格的情况要特殊判断,1*1也就是找输入的数的最大值,所以我们记录一下
				{
					maxx1=map[i][j];
				}
				sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+map[i][j];
			}
		}
		if(x==1&&y==1)//对于1*1进行特判
		{
			printf("%lld\n",maxx1);
			continue;
		}
		
		//	for(i=1; i<=n; i++)
		//	{
		//		for(j=1; j<=m; j++)
		//		{
		//			printf("%lld ",sum[i][j]);
		//		}
		//		printf("\n");
		//	}
		long long maxx=-1;
		for(i=1; i<=n-x+1; i++)//遍历寻找最大值,x-1是确定所取的方块的位置和大小
		{
			for(j=1; j<=m-y+1; j++)//y-1同上
			{
				long long sum1=sum[i+x-1][j+y-1]-sum[i+x-1][j-1]-sum[i-1][j+y-1]+sum[i-1][j-1];
				if(sum1>maxx)
				{
					maxx=sum1;
				}
			}
		}
		printf("%lld\n",maxx);
	}
	return 0;
}

发布了130 篇原创文章 · 获赞 3 · 访问量 1603

猜你喜欢

转载自blog.csdn.net/yeyuluo/article/details/103950848
今日推荐