有一個\(n\times m\)的網格,\((x,y)\)權值爲\(a_{x,y}\),要求從中選取三個不相交的\(k\times k\)的正方形使得它們權值最大。\(n,m,k\leqslant1500\)ios
其實,只有以下六種方法分割網格:git
對於每一種狀況,咱們在每一個小方格中找最大的\(k\times k\)的正方形相加便可。能夠令\(a[i][j],b[i][j],c[i][j],d[i][j]\)分別表示\((i,j)\)的左上、右上、左下、右下的區域中最大的\(k\times k\)的正方形的權值,而後就能夠計算了this
無spa
#include <cstdio> #include <iostream> #include <algorithm> #include <cctype> const int maxn = 1510; namespace io { struct istream { #define M (1 << 24) char buf[M], *ch = buf - 1; inline istream() { fread(buf, 1, M, stdin); } inline istream& operator >> (int &x) { while (isspace(*++ch)); for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15); return *this; } #undef M } cin; } int n, m, k, ans, s[maxn][maxn]; int a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], d[maxn][maxn]; /* * a | b * - - - * c | d */ int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); io::cin >> n >> m >> k; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) io::cin >> s[i][j]; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) s[i][j] += s[i][j - 1]; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) s[i][j] += s[i - 1][j]; for (int i = n; i >= k; --i) for (int j = m; j >= k; --j) s[i][j] += s[i - k][j - k] - s[i - k][j] - s[i][j - k]; for (int i = k; i <= n; ++i) for (int j = k; j <= m; ++j) a[i][j] = std::max({ s[i][j], a[i - 1][j], a[i][j - 1] }); for (int i = k; i <= n; ++i) for (int j = m - k + 1; j; --j) b[i][j] = std::max({ s[i][j + k - 1], b[i - 1][j], b[i][j + 1] }); for (int i = n - k + 1; i; --i) for (int j = k; j <= m; ++j) c[i][j] = std::max({ s[i + k - 1][j], c[i + 1][j], c[i][j - 1] }); for (int i = n - k + 1; i; --i) for (int j = m - k + 1; j; --j) d[i][j] = std::max({ s[i + k - 1][j + k - 1], d[i + 1][j], d[i][j + 1] }); for (int i = k; i <= n - k; ++i) for (int j = k; j <= m - k; ++j) ans = std::max(ans, a[i][j] + b[i][j + 1] + c[i + 1][m]); for (int i = k; i <= n - k; ++i) for (int j = k; j <= m - k; ++j) ans = std::max(ans, a[i][m] + c[i + 1][j] + d[i + 1][j + 1]); for (int i = k; i <= n - k; ++i) for (int j = k; j <= m - k; ++j) ans = std::max(ans, a[i][j] + c[i + 1][j] + b[n][j + 1]); for (int i = k; i <= n - k; ++i) for (int j = k; j <= m - k; ++j) ans = std::max(ans, a[n][j] + b[i][j + 1] + d[i + 1][j + 1]); for (int i = k; i <= n; ++i) for (int j = 2 * k; j <= m - k; ++j) ans = std::max(ans, s[i][j] + a[n][j - k] + b[n][j + 1]); for (int i = 2 * k; i <= n - k; ++i) for (int j = k; j <= m; ++j) ans = std::max(ans, s[i][j] + a[i - k][m] + c[i + 1][m]); std::cout << ans << '\n'; return 0; }