zoukankan      html  css  js  c++  java
  • [HNOI2003]激光炸弹

    [HNOI2003]激光炸弹

    给出一个平面直角坐标系,并给出其中n个整点,第i个点为((x_i,y_i)[x_i,y_iin[0,5000]]),第i个点上标记一个数字(v_i),现在请用一个(R imes R)的正方形,在其边界与x轴y轴对齐的同时,使覆盖的点上的标记的数字之和最大(R>0)

    可以转化为网格图问题,考虑方向,行列,对角线,矩形,按照枚举的思想,我们可以枚举正方向的右下角的顶点,时间复杂度是可以支持的,现在问题就变成如何快速查询一个正方形区域内的数字之和,显然维护一个二位数组前缀和,再配上查询操作即可,注意传统的方法不允许坐标为0,于是不妨把所有的坐标全部+1。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    using namespace std;
    int M[5050][5050];
    il int ask(int,int,int,int);
    template<class free>
    il free Max(free,free);
    int main(){
        int n,r,ans(0);scanf("%d%d",&n,&r);
        if(!r)return putchar(48),0;
        for(int i(1),y,x,v;i<=n;++i)
            scanf("%d%d%d",&y,&x,&v),M[y+1][x+1]=v;
        for(int i(1),j;i<=5001;++i)
            for(j=1;j<=5001;++j)
                M[i][j]+=M[i-1][j]+M[i][j-1]-M[i-1][j-1];
        for(int i(1),j,y,x;i<=5001;++i)
            for(j=1;j<=5001;++j){
                y=i+r-1,x=j+r-1;
                if(y>5001)y=5001;if(x>5001)x=5001;
                ans=Max(ans,ask(y,x,i,j));
            }
        printf("%d",ans);
        return 0;
    }
    template<class free>
    il free Max(free a,free b){
        return a>b?a:b;
    }
    il int ask(int y1,int x1,int y2,int x2){
        return M[y1][x1]-M[y1][x2-1]-M[y2-1][x1]+M[y2-1][x2-1];
    }
    
    
  • 相关阅读:
    Android将ScrollView移动到最底部
    Android权限之sharedUserId和签名
    python接口使用及工具函数
    python模块(json、os、sys、random、string、time、hashlib)
    python内置函数
    python模块、函数变量及递归
    python数据类型集合及函数
    python文件操作及修改
    python字符类型操作及文件操作
    jmeter压测
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11205264.html
Copyright © 2011-2022 走看看