BZOJ-1177 [Apio2009]Oil
解题思路:
一种非常神奇的枚举策略...不过这种枚举策略...是需要DP来完成的
嘛...这种神奇的题目我独立肯定是做不来的...所以我是看着这篇博客写的...传送门
嘛...这篇博客好就好在...你必须要想通了你才知道这个代码是怎么回事...太可怕了%%%
首先,因为题目说了, 必须要是三个k*k的矩形,那么其实相对来说比较容易的想法就是一个个去枚举,但是肯定会超时。
那么考虑一个问题,就是这三个矩形的位置大概是怎么样的。
既然这三个矩形是互相不相交的,那么肯定就只有6种情况。
就是这样的6种情况...嘛用Windows自带的画图画的...有点丑...不要在意细节
这样...用a,b,c,d四个数组,先描述出左上,右上,左下,右下的前面的最大的k*k矩阵和
然后再分别描述这六幅图的情况,就可以求出最大值了。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int maxn = 1505; int sum[maxn][maxn]; int a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], d[maxn][maxn]; int main() { int m, n, k, val; scanf("%d%d%d", &m, &n, &k); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { scanf("%d", &val); sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + val; } } for (int i = m; i >= k; --i) { for(int j = n; j >= k; --j) sum[i][j] -= sum[i - k][j] + sum[i][j - k] - sum[i - k][j - k]; } //求出四个最大前缀 for (int i = k; i <= m; ++i) { for (int j = k; j <= n; ++j) a[i][j] = max(sum[i][j], max(a[i - 1][j], a[i][j - 1])); } for (int i = k; i <= m; ++i) { for (int j = n; j >= k; --j) b[i][j] = max(sum[i][j], max(b[i - 1][j], b[i][j + 1])); } for (int i = m; i >= k; --i) { for (int j = k; j <= n; ++j) c[i][j] = max(sum[i][j], max(c[i + 1][j], c[i][j - 1])); } for (int i = m; i >= k; --i) { for (int j = n; j >= k; --j) d[i][j] = max(sum[i][j], max(d[i + 1][j], d[i][j + 1])); } //枚举六种情况,求出最大值 int ans = 0; for (int i = k; i <= m - k; ++i) { for (int j = k; j <= n - k; ++j) ans = max(ans, a[i][j] + b[i][j + k] + c[i + k][n]); } for (int i = k; i <= m - k; ++i) { for (int j = (k << 1); j <= n; ++j) ans = max(ans, a[m][j - k] + b[i][j] + d[i + k][j]); } for (int i = k; i <= m - k; ++i) { for (int j = k; j <= n - k; ++j) ans = max(ans, a[i][j] + b[m][j + k] + c[i + k][j]); } for (int i = (k << 1); i <= m; ++i) { for (int j = k; j <= n - k; ++j) ans = max(ans, a[i - k][n] + c[i][j] + d[i][j + k]); } for (int i = k; i <= m; ++i) { for (int j = (k << 1); j <= n - k; ++j) ans = max(ans, sum[i][j] + a[m][j - k] + b[m][j + k]); } for (int i = (k << 1); i <= m - k; ++i) { for (int j = k; j <= n; ++j) ans = max(ans, sum[i][j] + a[i - k][n] + c[i + k][n]); } printf("%d\n", ans); //system("pause"); return 0; }