[关闭]
@WangYixu 2018-06-17T04:44:55.000000Z 字数 1460 阅读 1741

[APIO2009]采油区域

OI 题解

这个题要求三个不相交区域权值和最大,这样的话,不难想到先计算出来每个可能的区域,即利用前缀和的思想。

又有三个不相交的正方形只有6种相对位置关系:

此处输入图片的描述

分六种情况讨论即可。

如果预先处理出某个点左上、左下、右上、右下部分的最大区域,对于左边4种情况,枚举交点位置即可,对于另外两种情况,可以在固定中间区域边界线的情况下枚举中间的矩形在哪个位置。(具体处理方法见代码)

代码

  1. #include<cstdio>
  2. #include<algorithm>
  3. using std::max;
  4. // 为了减少代码量
  5. #define REP(i, j, k) for (int i = (j); i <= (k); ++i)
  6. #define DEC(i, j, k) for (int i = (j); i >= (k); --i)
  7. typedef long long ll;
  8. const int N = 1500 + 10;
  9. ll a[N][N], UL[N][N], UR[N][N], DL[N][N], DR[N][N], s[N][N];
  10. int n, m, k;
  11. int main() {
  12. scanf("%d%d%d", &n, &m, &k);
  13. REP(i, 1, n) REP(j, 1, m) {
  14. scanf("%lld", &a[i][j]);
  15. s[i][j] = s[i][j-1] + s[i-1][j] - s[i-1][j-1] + a[i][j]; // 计算前缀和
  16. }
  17. // 计算k*k区域权值
  18. DEC(i, n, k) DEC(j, m, k)
  19. s[i][j] = s[i][j] - s[i-k][j] - s[i][j-k] + s[i-k][j-k];
  20. //DP计算每个点的四个方位的最大k*k区域
  21. REP(i, k, n) REP(j, k, m)
  22. UL[i][j] = max(s[i][j], max(UL[i-1][j], UL[i][j-1]));
  23. REP(i, k, n) DEC(j, m - k + 1, 1)
  24. UR[i][j] = max(s[i][j+k-1], max(UR[i-1][j], UR[i][j+1]));
  25. DEC(i, n - k + 1, 1) REP(j, k, m)
  26. DL[i][j] = max(s[i+k-1][j], max(DL[i+1][j], DL[i][j-1]));
  27. DEC(i, n - k + 1, 1) DEC(j, m - k + 1, 1)
  28. DR[i][j] = max(s[i+k-1][j+k-1], max(DR[i+1][j], DR[i][j+1]));
  29. // 分情况讨论:
  30. // 1.前四种
  31. ll ans = 0;
  32. if(2*k <= n && 2*k <= m) // 别忘了限制条件
  33. REP(i, 1, n) REP(j, 1, m) {
  34. /*|-| |*/ans = max(ans, UL[i][j] + DL[i+1][j] + UR[n][j+1]);
  35. /*| |-|*/ans = max(ans, UR[i][j] + DR[i+1][j] + UL[n][j-1]);
  36. /*|-`-|*/ans = max(ans, UL[i][j] + UR[i][j+1] + DR[i+1][1]);
  37. /*|-.-|*/ans = max(ans, DL[i][j] + DR[i][j+1] + UR[i-1][1]);
  38. }
  39. // 2.后两种
  40. if (3*k<= n)
  41. REP(i, 2 * k, n - k) REP(j, k, m)
  42. ans = max(ans, UL[n][j - k] + UR[n][j+1] + s[i][j]);
  43. if (3*k<= m)
  44. REP(i, k, n) REP(j, 2 * k, m - k)
  45. ans = max(ans, UL[i - k][m] + DL[i+1][m] + s[i][j]);
  46. printf("%lld\n", ans);
  47. return 0;
  48. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注