二维前缀和应用

题目链接:http://172.18.66.54:50015/problem.php?id=1472

题目描述

AW最近比较佛系,开始玩起了种田游戏养生。AW在种田的时候遇到了一个问题,在一块 n×m 个方格的地图上,他想围一块边长为 k 的正方形土地当做西瓜田,但是每个方格的土地肥沃度 w 并不一样,AW想围出一块肥沃度之和最大的土地,请你帮帮他。

输入

一个整数t,表示t组测试数据。

 

对于每组测试数据,第一行三个整数n, m(1 <= n, m <= 500), k。含义如上所示并且k保证合法。

 

接下来有n行m列个正整数 w(0 <= w <= 1000),表示每块土地的肥沃度。

输出

每组样例两个整数x, y。表示以地图左上角方格为(1,1)开始的坐标系中,西瓜田左上角的坐标。(横轴表示x,纵轴表示y)

 

如果有多个满足题意的答案,输出坐标最小(先取x最小,x相同取y最小)的那个答案。

样例输入

2
2 2 1
1 2
3 4
3 3 2
10 10 10
20 10 30
0 10 0

样例输出

2 2
2 1

这题正解是用二维前缀和求的,边读入就能边求出答案。Dp[i][j]就是从(1,1)(I,J)的长方形中的数据之和,于是就能得出以(I,J)为右下角的正方形农田的肥沃度之和。

AC代码:

#include <bits/stdc++.h>
using namespace std;

#define rld(x) scanf("%lld",&(x))
#define rd(x) scanf("%d",&(x))
#define sc scanf
#define pf printf
typedef long long ll;

const int N = 1e3+5;
ll dp[N][N];

int main(void){
    int t; rd(t);
    while(t--){
        int n,m,k;
        sc("%d%d%d", &n, &m, &k);
        int tt = 0, x, y;
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=m; ++j){
                rld(dp[i][j]);
                dp[i][j] += dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1];
                if( k<=i && k<=j ){
                    int w = dp[i][j]-dp[i][j-k]-dp[i-k][j]+dp[i-k][j-k];
                    if(tt < w){
                        tt = w;
                        x = j - k + 1;
                        y = i - k + 1;
                    }
                }
            }
        }
        pf("%d %d\n", x, y);
    }
    return 0;
}

 

posted @ 2019-08-25 19:14  Shmilky  阅读(68)  评论(0编辑  收藏  举报