Codeforces 263E

Codeforces 263E

原题
题目描述:一个(n imes m)的矩阵,每格有一个数,给出一个整数(k),定义函数(f(x, y)):

[f(x, y)=sum_{i=1}^{n} sum_{j=1}^{m} a_{i, j} cdot max(0, k-|i-x|-|j-y|) (k leq x leq n-k+1, k leq y leq m-k+1) ]

求使(f(x, y))最大的一个二元对((x, y))

solution
我表示只会暴力部分和

1、(sum_{p=1}^{i} a_{i-p+1, j})

2、(sum_{p=1}^{k} a_{i-p+1, j}*(k-p+1))

3、(sum_{p=1}^{k} a_{i-p+1, j+p-1})

4、以图为例,(k=3, (3, 4))为红色圈住的部分每个数*1
5、以图为例, (k=3, (3, 4)) 为 $ ( ( 4 + 6 + 7 ) imes 1+ ( 2 + 6 ) imes 2+ 8 imes 3) $

然后旋转三次, 每次算的时候减去最高那列(图为减去第4列),加起来就是答案了。

AC的人中好像有更神的算法,就是把图斜着看,那就是求正方形的和了。

code

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <complex>
#include <set>
#include <map>
#include <stack>
using namespace std;

const int maxn=1010;
typedef long long LL;

int n, m, lim;
int a[maxn][maxn], tmpa[maxn][maxn];
LL f[maxn][maxn], tmpf[maxn][maxn];
LL sum[maxn][maxn][7];

void init()
{
	scanf("%d%d%d", &n ,&m, &lim);
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			scanf("%d", &a[i][j]);
}
void prepare()
{
	int fi=max(n, m);
	for (int i=1; i<=fi; ++i)
		for (int j=1; j<=fi; ++j)
			for (int k=1; k<=5; ++k)
				sum[i][j][k]=0;
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
		{
			//row and once
			sum[i][j][1]=sum[i-1][j][1]+a[i][j];
			//row and in order
			LL up=(i-1>=lim? sum[i-1-lim][j][1]:0);
			sum[i][j][2]=sum[i-1][j][2]-(sum[i-1][j][1]-up)+LL(lim)*a[i][j];
			//bevel
			sum[i][j][3]=sum[i-1][j+1][3]+a[i][j];
			//triangle and once
			up=(i>=lim? sum[i-lim][j][3]:0);
			LL L;
			if (j-1>=lim) L=sum[i][j-lim][3];
			else
			L=(i-(lim-(j-1))>0? sum[i-(lim-(j-1))][1][3]:0);

			sum[i][j][4]=sum[i][j-1][4]-(L-up)+sum[i][j][1]-(i>=lim? sum[i-lim][j][1]:0);
			//triangle and in order
			sum[i][j][5]=sum[i][j-1][5]-sum[i][j-1][4]+sum[i][j][2];
		}
}
void turn()
{
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			tmpa[i][j]=a[i][j];
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			a[m-j+1][i]=tmpa[i][j];

	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			tmpf[i][j]=f[i][j];
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			f[m-j+1][i]=tmpf[i][j];
	swap(n, m);
}
void solve()
{
	for (int i=1; i<=4; ++i)
	{
		prepare();
		for (int j=1; j<=n; ++j)
			for (int k=1; k<=m; ++k)
				f[j][k]+=sum[j][k][5]-sum[j][k][2];
		turn();
	}
	for (int i=1; i<=n; ++i)
		for (int j=1; j<=m; ++j)
			f[i][j]+=a[i][j]*lim;

	int x=0, y=0;
	LL ans=-1;
	for (int i=lim; i<=n-lim+1; ++i)
		for (int j=lim; j<=m-lim+1; ++j)
			if (f[i][j]>ans)
			{
				x=i; y=j;
				ans=f[i][j];
			}
	printf("%d %d
", x, y);
}
int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	init();
	solve();
	return 0;
}


原文地址:https://www.cnblogs.com/GerynOhenz/p/4963241.html