代码有点复杂,所以先写下思路吧
设fi,j为以(i,j)为正方形左上角时的土地价值和,考虑如何转移:
预处理:hi,j表示以(i,j)为左端点,长度为c的一行土地价值和 ;
li,j表示以(i,j)为上顶点,长度为c的一列土地价值和。
预处理复杂度为O(n2)。
转移:对于f1,1,暴力算出其值
对于f1,j (j>1),由f1,j−1推得 :f1,j=f1,j−1−l1,j−1+l1,j+c−1
对于fi,j (i>1),由fi−1,j推得:fi,j=fi−1,j−hi−1,j+hi+c−1,j
转移复杂度也为O(n2)。
/* 只获得了85pts qaq看了半天也没看出来哪不对*/
#include<iostream>
#include<cstdio>
#pragma warning(disable:4996)
using namespace std;
const int N = 1e3 + 5;
int n, m, c, ansi, ansj;
long long mp[N][N], h[N][N], l[N][N], f[N][N], ans = -9e18;
int main() {
cin >> n >> m >> c;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> mp[i][j];
for(int i = 1;i <= n;i++)
for (int j = m;j >= 1;j--) {
if (j + c > m)h[i][j] = h[i][j + 1] + mp[i][j];
else h[i][j] = h[i][j + 1] + mp[i][j] - mp[i][j + c];
}
for (int j = 1;j <= m;j++)
for (int i = n;i >= 1;i--) {
if (i + c > n)l[i][j] = l[i + 1][j] + mp[i][j];
else l[i][j] = l[i + 1][j] + mp[i][j] - mp[i + c][j];
}
for (int i = 1;i <= c;i++)
f[1][1] += h[i][1];
for (int j = 2;j <= m;j++)
f[1][j] = f[1][j - 1] + l[1][j + c - 1] - l[1][j - 1];
for (int i = 2;i <= n;i++)
for (int j = 1;j <= m;j++)
f[i][j] = f[i - 1][j] + h[i + c - 1][j] - h[i - 1][j];
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
if (f[i][j] > ans) {
ans = f[i][j];
ansi = i, ansj = j;
}
printf("%d %d", ansi, ansj);
return 0;
}