算法:二维数组前缀和

二维数组前缀和用于快速求解矩形区域内的元素和。通过预先计算每行每列的和,可以利用相邻元素的前缀和计算目标区域的总和。在C++代码示例中展示了如何构建前缀和表并使用get_sum函数高效地获取子矩阵的和,处理了边界条件。这种方法常用于解决动态规划和矩阵操作的问题。
摘要由CSDN通过智能技术生成

二维数组前缀和有什么用?
求A[i][j]和A[m][n]之间所有元素加起来的总和。
在这里插入图片描述
定义:
sun[i][j]是A[0][0]到A[i][j]的前缀和

sum[x1,y1][x2,y2]=sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]
在这里插入图片描述
那sum[i][j]要怎么求呢?
sum[i][j]=A[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]
在这里插入图片描述
也就是该元素A[i][j]左侧第一个和上方第一个的sum值相加再减去重复加上的部分。

关于边界问题:
当i=0,j=0时 sum[0][0]=A[0][0]
sum[0,0]0,0=A[0][0]

当i等于0时就变成了一维前缀和
sum[0][j]=sum[0][j-1]+A[0][j]
sum[0,y1][0,y2]=sum[0][y2]-sum[0][y1-1]
当j等于0时此时只有第一列,同理为一维前缀和
sum[i][0]=sum[i-1][0]+A[i][0]
sum[x1,0][x2,0]=sum[x2][0]-sum[x1-1][0]

代码如下:

#include<iostream>
#include<Windows.h>
using namespace std;
const int n=3,m=4;
int A[n][m]={
    {1,5,6,8},
    {9,6,7,3},
    {5,3,2,4},
};
int sum[n][m];
//构造sum表
int per_sum(){
    sum[0][0]=A[0][0];
    for(int j=1;j<m;j++)//第一行
        sum[0][j]=sum[0][j-1]+A[0][j];
    for(int i=1;i<n;i++)//第一列
        sum[i][0]=sum[i-1][0]+A[i][0];
    for(int i=1;i<n;i++){
        for(int j=1;j<m;j++){
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+A[i][j];
        }
    }
}
int get_sum(int x1,int y1,int x2,int y2){
    int res;
    if(x1==0&&x2==0)
        return res=sum[x2][y2];
    if(x1==0)
        return res=sum[x2][y2]-sum[x2][y1-1];
    if(y1==0)
        return res=sum[x2][y2]-sum[x1-1][y2];
    return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];

}
int main(){
    per_sum();
    cout<<get_sum(1,1,2,2)<<endl;
    cout<<get_sum(0,1,1,3)<<endl;
    system("pause");
    return 0;
}
per_sum()函数相当于是构造了一张sum表,这张表的里的内容是[0][0]到该点[x][y]之间所有元素的和。
这张表的构造方式是首先构造第一行和第一列,然后构造其他元素时用到第一行和第一列的值。

get_sum()为(x1,y1)到(x2,y2)之间元素值的和。这里要讨论边界问题,因为sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]的前提是x1,y1 x2,y2大于0的情况,所以要讨论各自为零和都为零的情况。

最终结果如下:
在这里插入图片描述
总结一下:
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值