洛谷 P2280 [HNOI2003]激光炸弹

洛谷 P2280 [HNOI2003]激光炸弹

题目:

题解:

  • 二维前缀和。
  • 诈一看似乎是线段树/暴力?
  • 首先第一个难点是题目说目标位于爆破正方形边上的不算。这个问题怎么解决。其实就可以把每个目标的坐标向右上角平移一位。
  • 举个例子,(0, 0)和(1, 1),原本sum(1, 1)是2的(不符合题意);平移之后变成了(1, 1)和(2, 2),sum(1, 1)变成了1,符合题意。
  • 第二个难点是题目说炸弹为正方形,所以以(i, j)为右上角的答案就不是简单的sum(i, j) = sum(i - 1, j) + sum(i, j - 1) - sum(i - 1, j - 1)了。而是在更新完sum后,每次ans取max,如下↓
    • ans = max(ans, sum(i, j) - sum(i - r, j) - sum(i, j - r)+ sum(i - r, j - r))
    • 这样就能保证取到的ans是以(i, j)为右上角的正方形(强烈建议画图理解)
#include <iostream>
#include <cstdio>
#define maxn 5005
using namespace std;

int n, r, ans;
int sum[maxn][maxn];

int main()
{
    cin >> n >> r;
    for(int i = 1; i <= n; i++)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        sum[x + 1][y + 1] = z;
    }
    for(int i = 1; i <= 5000; i++)
        for(int j = 1; j <= 5000; j++)
            sum[i][j] += (sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]); 
    for(int i = r; i <= 5000; i++)
        for(int j = r; j <= 5000; j++)
            ans = max(ans, sum[i][j] - sum[i - r][j] - sum[i][j - r] + sum[i - r][j - r]);
    cout << ans;
    return 0;   
}

猜你喜欢

转载自www.cnblogs.com/BigYellowDog/p/11203149.html