二维前缀和应用
题目链接: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;
}