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;
}