Codeforces 263E

Codeforces 263E

原题
题目描述:一个\(n \times 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 ) \times 1+ ( 2 + 6 ) \times 2+ 8 \times 3) $
733825-20151113210923712-884407020.png

然后旋转三次, 每次算的时候减去最高那列(图为减去第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\n", 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值