问题 D: 约会-UPC三十场(前缀和)

题目描述
从前,小兔发现了一个神秘的花园。

花园是一个 n 行 m 列的矩阵,第 i 行 j 列的花的美丽度为 ai,j,一个合法的约会场所为任意一个正方形子矩阵,定义子矩阵的浪漫度为这个子矩阵的两条对角线上的花的美丽度之和。

现在小兔想选一个面积大等于 1 的约会场所使得场所的浪漫度最大,以便和小鹿约会,因为小兔忙着 AKIOI ,所以她把这个问题交给了你。
输入
第一行,两个正整数 n,m。
接下来是一个 n 行 m 列的矩阵,表示各个位置上花的美丽度。
输出
仅一行,一个正整数,表示最大的浪漫度。
样例输入 Copy
3 3
2 -1 3
-4 2 1
1 2 -1
样例输出 Copy
7
提示
对于 40%的数据,n,m≤10。
对于 100%的数据,1≤n,m≤300,∣ai∣≤104。

思路
如果直接暴力能过的话,你我此时此刻也不会在此见面
不过也跟暴力没什么区别,维护对角线的前缀和
用B数组维护主对角线的前缀和,用C数组维护副对角线的前缀和
然后枚举左上角的点和正方形的边长
然后O(1) 获得 浪漫度,
最后取max

代码

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdio>
#include <bitset>
#include <vector>
#include <iomanip>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define UpMing main
#define re register
#pragma GCC optimize(2)
#define Accept return 0;
#define lowbit(x) ((x)&(-(x)))
#define mst(x, a) memset(x,a,sizeof(x))
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
const int inf =0x3f3f3f3f;
const int maxn=2e6+7;
const ll mod = 998244353;
const int N =1e6+7;
inline ll read() {
    
    
	ll  x=0;
	bool f=0;
	char ch=getchar();
	while (ch<'0'||'9'<ch)    f|=ch=='-', ch=getchar();
	while ('0'<=ch && ch<='9')
		x=x*10+ch-'0',ch=getchar();
	return f?-x:x;
}
void out(ll x) {
    
    
	int stackk[20];
	if(x<0) {
    
    
		putchar('-');
		x=-x;
	}
	if(!x) {
    
    
		putchar('0');
		return;
	}
	int top=0;
	while(x) stackk[++top]=x%10,x/=10;
	while(top) putchar(stackk[top--]+'0');
}
ll a[1333][1333],n,m,ans,b[1311][1313],c[1311][1313];
ll f(ll x,ll y,ll z) {
    
    
	if(z%2)
		return (b[x+z][y+z]-b[x-1][y-1])+(c[x+z][y]-c[x-1][y+z+1]);
	else
		return (b[x+z][y+z]-b[x-1][y-1])+(c[x+z][y]-c[x-1][y+z+1])-a[x+z/2][y+z/2];
}
int UpMing() {
    
    
	cin>>n>>m;
	for(int i=1 ; i<=n ; i++)
		for(int j=1 ; j<=m ; j++) {
    
    
			cin>>a[i][j];
			ans=max(ans,a[i][j]);
		}
	for(int i=1 ; i<=n ; i++)
		for(int j=1 ; j<=m ; j++) {
    
    
			for(int x=i,y=j; x<=n&&y<=m ; y++,x++)
				b[x][y]=b[x-1][y-1]+a[x][y];
		}
		
	for(int i=1 ; i<=n ; i++)
		for(int j=1 ; j<=m ; j++) {
    
    
			for(int x=i,y=j; x<=n&&y>=1 ; y--,x++)
				c[x][y]=c[x-1][y+1]+a[x][y];
		}

	for(int len=1 ; len<min(n,m); len++)
		for(int i=1 ; i<=n-len ; i++)
			for(int j=1 ; j<=m-len; j++)
				ans=max(ans,f(i,j,len));
				
	out(ans);
	Accept;
}

/*
3 3
2 -1 3
-4 2 1
1 2 -1

*/


猜你喜欢

转载自blog.csdn.net/wmy0536/article/details/106423207