C++ 算法学习——1.6 前缀和与二维前缀和算法

news/2024/10/7 18:18:04 标签: c++, 算法, 学习

前缀和算法(Prefix Sum Algorithm):

  1. 概念前缀和算法通过在遍历数组时计算前缀和(从数组的第一个元素开始累加到当前元素的和),可以在O(1)时间内得到任意区间的子数组和,而不需要重复计算。

  2. 算法步骤

    • 遍历数组,计算每个位置的前缀和,并存储在另一个数组中。
    • 计算任意区间和时,利用前缀和数组直接计算区间两端位置的前缀和之差即可得到区间和。
  3. 应用:前缀和算法常用于解决一维数组中的区间和问题,例如最大子数组和、子数组和为0的最长子数组等。

  4. 构建示例

    for (int i = 1; i < n; i++) {
            prefixSum[i] = prefixSum[i - 1] + nums[i];
        }


二维前缀和算法(2D Prefix Sum Algorithm):

  1. 概念:二维前缀和算法是在二维数组或矩阵上的扩展,用于快速计算矩阵中任意矩形区域的和。

  2. 算法步骤

    • 遍历二维数组,计算每个位置的二维前缀和,即该位置左上方所有元素的和
    • 计算任意矩形区域和时,利用二维前缀和数组可以在O(1)时间内计算出该区域的和。
  3. 应用:二维前缀和算法常用于解决二维矩阵中的区域和问题,例如二维区域和为0的最大子矩阵和、矩形区域和等。

  4. 计算与构建示例

    int getSubmatrixSum(int** prefixSum, int row1, int col1, int row2, int col2) {
        int sum = prefixSum[row2][col2];
        if (row1 > 0) {
            sum -= prefixSum[row1 - 1][col2];
        }
        if (col1 > 0) {
            sum -= prefixSum[row2][col1 - 1];
        }
        if (row1 > 0 && col1 > 0) {
            sum += prefixSum[row1 - 1][col1 - 1];
        }
        return sum;
    }
    int** build2DPrefixSumArray(const int** matrix, int rows, int cols) {
        // 分配内存来存储前缀和数组
        int** prefixSum = new int*[rows];
        for (int i = 0; i < rows; i++) {
            prefixSum[i] = new int[cols];
        }
    
        // 初始化前缀和数组
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                prefixSum[i][j] = 0;
            }
        }
    
        // 计算第一行的前缀和
        for (int j = 0; j < cols; j++) {
            prefixSum[0][j] = matrix[0][j]+prefixSum[0][j-1];
        }
    
        // 计算第一列的前缀和
        for (int i = 1; i < rows; i++) {
            prefixSum[i][0] = prefixSum[i - 1][0] + matrix[i][0];
        }
    
        // 计算其他位置的前缀和
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < cols; j++) {
                prefixSum[i][j] = matrix[i][j] + prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1];
            }
        }
    
        return prefixSum;
    }

P1. 洛谷p1719最大加权矩形 

#include <iostream>
#include <cmath>
using namespace std;

int getSubmatrixSum(int** prefixSum, int row1, int col1, int row2, int col2) {
    int sum = prefixSum[row2][col2];
    if (row1 > 0) {
        sum -= prefixSum[row1 - 1][col2];
    }
    if (col1 > 0) {
        sum -= prefixSum[row2][col1 - 1];
    }
    if (row1 > 0 && col1 > 0) {
        sum += prefixSum[row1 - 1][col1 - 1];
    }
    return sum;
}

int main() {
    int ans = 0;
    int n;
    cin >> n;
    
    // 创建二维矩阵
    int** mat = new int*[n];
    for (int i = 0; i < n; i++) {
        mat[i] = new int[n];
    }

    // 读取矩阵元素
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> mat[i][j];
        }
    }

    // 创建前缀和数组
    int** prefixSum = new int*[n];
    for (int i = 0; i < n; i++) {
        prefixSum[i] = new int[n];
    }

    // 计算前缀和数组
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            prefixSum[i][j] = mat[i][j];
            if (i > 0) {
                prefixSum[i][j] += prefixSum[i - 1][j];
            }
            if (j > 0) {
                prefixSum[i][j] += prefixSum[i][j - 1];
            }
            if (i > 0 && j > 0) {
                prefixSum[i][j] -= prefixSum[i - 1][j - 1];
            }
        }
    }

    // 计算最大子矩阵和
    for (int row1 = 0; row1 < n; row1++) {
        for (int col1 = 0; col1 < n; col1++) {
            for (int row2 = row1; row2 < n; row2++) {
                for (int col2 = col1; col2 < n; col2++) {
                    ans = max(getSubmatrixSum(prefixSum, row1, col1, row2, col2), ans);
                }
            }
        }
    }

    cout << ans;

    // 释放内存
    for (int i = 0; i < n; i++) {
        delete[] mat[i];
        delete[] prefixSum[i];
    }
    delete[] mat;
    delete[] prefixSum;

    return 0;
}


http://www.niftyadmin.cn/n/5693185.html

相关文章

停车场停车位检测数据集2166张 违停 带标注 voc yolo 2类

停车场停车位检测数据集2166张 违停 带标注 voc yolo 2类 分类名: (图片张数&#xff0c;标注个数) occupied :(1035&#xff0c;2634) empty: (1131, 4280) 总数:(1230&#xff0c;691 4) 总类(nc): 2类 停车场停车位检测数据集介绍 数据集名称 停车场停车位检测数据集 (Pa…

BGP路由原理详解

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏 华为_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 一. BGP简介: 二. BGP报文中的角色 BGP的报文 BGP处理过程 BGP有限状态机 BGP属性 三. BGP作用 四. BGP选路 ​…

Golang | Leetcode Golang题解之第458题可怜的小猪

题目&#xff1a; 题解&#xff1a; func poorPigs(buckets, minutesToDie, minutesToTest int) int {if buckets 1 {return 0}combinations : make([][]int, buckets1)for i : range combinations {combinations[i] make([]int, buckets1)}combinations[0][0] 1iterations…

每日一题|871. 最低加油次数|动态规划、内层逆序遍历

题目分析&#xff1a;找到第一个能够实现当前油量能够行驶的最大距离大于等于目标距离&#xff0c;且加油次数最小的加油站和加油次数。 每次加油之后能够行驶的最大距离都是由上一次加油的距离决定的&#xff0c;因此使用dp。 1、dp数组定义 dp[i]是一个一维数组&#xff0…

鸿蒙next开发者第一课02.DevEcoStudio的使用-习题

【习题】DevEco Studio的使用 通过/及格分80/ 满分100 判断题 1. 如果代码中涉及到一些网络、数据库、传感器等功能的开发&#xff0c;均可使用预览器进行预览。F 正确(True)错误(False) 预览器不能进行传感器等特殊功能的开发,需要使用真机开发 2. module.json5文件中的…

class 031 位运算的骚操作

这篇文章是看了“左程云”老师在b站上的讲解之后写的, 自己感觉已经能理解了, 所以就将整个过程写下来了。 这个是“左程云”老师个人空间的b站的链接, 数据结构与算法讲的很好很好, 希望大家可以多多支持左程云老师, 真心推荐. 左程云的个人空间-左程云个人主页-哔哩哔哩视频…

专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结

目录 搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜 1.深度优先遍历 vs 深度优先搜索(dfs) 2.宽度优先遍历 vs 宽度优先搜索(bfs) 2.关系图暴力枚举一遍所有的情况 3.拓展搜索问题全排列 决策树 1. 计算布尔⼆叉树的值&#xff08;medi…

redis——哨兵机制

redis中提供了哨兵&#xff08;Sentinel&#xff09;机制来实现主从集群的自动故障恢复。 主从复制是实现redis高可用性的基石&#xff0c;从节点宕机时我们仍然可以将请求发送给主节点或者其他从节点&#xff0c;而当主节点宕机的时候&#xff0c;无法执行写操作&#xff0c;无…