洛谷 P2280 鐳射炸彈

薛定谔的AC發表於2024-06-16

題目連結:鐳射炸彈



思路

看到消滅一個正方形內的所有目標就會想到二維字首和。輸入的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;
}