审题:
本题需要我们找出激光炸弹所能炸毁的最大价值并打印
思路:
方法一:二维前缀和炸弹缺陷分析:题目中说目标若位于炸弹的边上就不能炸毁目标,其实是要求我们的炸弹必须完全包围目标方可炸毁
图示的阴影区域是m为1的激光炸弹,如果我们如图摆放炸弹,那么将没有目标被炸毁,因为没有一个目标是完全被炸弹包围住的
总体思路:
1.计算二维前缀和f:f[i][j]表示以(0,0)坐标为矩形左上角到以(i,j)坐标位矩形右下角的矩形区域的价值之和
2.枚举所有炸弹摆放情况:由于炸弹只能与x轴y轴平行的摆放,所以我们可以根据右下角坐标和边长m来枚举确定所有摆放情况
3.计算每个摆放情况的炸弹炸毁价值总和并用max维护answer,确保遍历结束后answer就是最大炸毁价值
解题:
nclude<iostream> using namespace std; int n, m; const int N = 5010; int a[N][N];//记录初始状态 int f[N][N];//前缀和 int answer; int main() { cin >> n >> m; while (n--) { int x, y, v; cin >> x >> y >>v; x++, y++;//将索引基准升为1 a[x][y] += v;//每一个位置价值可能重复叠加 } //前缀和计算 for (int i = 1; i <= 5001; i++) { for (int j = 1; j <= 5001; j++) { f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + a[i][j]; } } m = min(m, 5001);//将m大于整个区域的情况兼容 //枚举右下角坐标所有情况 for (int i = m; i <= 5001; i++) { for (int j = m; j <= 5001; j++) { int x1 = i - m + 1; int y1 = j - m + 1; int sum = f[i][j] - f[x1 - 1][j] - f[i][y1 - 1] + f[x1-1][y1-1]; answer = max(answer, sum); } } cout << answer << endl; return 0; }
1.本题中坐标的边界就是5000,所以我们将N定义为5010就足够用来定义数组a和f了
2.记录数据的时候注意要用+=符号来添加,因为题目中说明了同一个位置可能存在多个目标,所以一个坐标位置的价值可能会叠加
3.为了兼容m大于边界的情况,我们将这种情况的m置为边界即可
注意:x1 + m -1 = i ; y1 + m - 1 = j
因为本题需要炸弹将整个矩形包围,所以x1和i之间的差值是m-1
算法题(130):激光炸弹
于 2025-04-21 20:21:54 首次发布