洛谷 P2280 激光炸弹

题目链接:激光炸弹



思路

       看到消灭一个正方形内的所有目标就会想到二维前缀和。输入的x, y可能相同,所以同一个位置可能会有多个目标所以在初始化的时候需要使用dp[x + 1][y + 1] += v;,而不是dp[x + 1][y + 1] = v。为了使得二维前缀和计算的时候不会数组越界,所以将地图范围改为[1, 5001],使得在使用公式dp[i][j] += dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1]的时候不用分类讨论。
       二维前缀和:只能摧毁边长为m的正方形内的所有目标,所以需要依靠二维前缀和来求出一个长方形内的所有目标的总价值,如dp[i][j] - dp[i - m][j] - dp[i][j - m] + dp[i - m][j - m],然后枚举每个变长为m的正方形的右下角顶点的位置,并不断更新最大总价值res。


代码

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;
#define ll long long

ll n, m;
ll dp[N][N];

int main() {
  cin >> n >> m;

  for (int i = 1; i <= n; i++) {
    ll x, y, v;
    cin >> x >> y >> v;
    dp[x + 1][y + 1] += v;
  }

  for (int i = 1; i <= 5e3 + 5; i++) {
    for (int j = 1; j <= 5e3 + 5; j++) {
      dp[i][j] += dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - 1];
    }
  }

  ll res = 0;
  for (int i = m; i <= 5e3 + 5; i++) {
    for (int j = m; j <= 5e3 + 5; j++) {
      res = max(res, dp[i][j] - dp[i - m][j] - dp[i][j - m] + dp[i - m][j - m]);
    }
  }
  cout << res << endl;
  return 0;
}
posted @ 2024-06-16 01:34  薛定谔的AC  阅读(13)  评论(0编辑  收藏  举报