題目連結:鐳射炸彈
思路
看到消滅一個正方形內的所有目標就會想到二維字首和。輸入的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;
}