求子矩阵的和,二维数组指定区域的和(前缀和二维)


**关于一维数组的前缀和(求指定区间的所有数的和)文章说明 一维数组前缀和

一、例题

求黄色区域的和
在这里插入图片描述
大家可以思考一下这题具体应该怎么做,这里提供给大家几种思路,一种是把这个二维数组分为几行来看,求每一行的指定区间的和,然后把每一行的和加起来,分成几列也是一样的道理;另一种是二重循环,从左上角顶点作为起始点,右下角顶点作为终点把所有数加起来。缺点: 这两种方法总体来说时间复杂度比前缀和方法高,并且操作比较麻烦,如果想连续多次求不同区域的和的话,就要每次都重新输入,不如前缀和简单。

二、前缀和解题思路

做到这题的时候,我们不妨把它离散化,所谓离散化就是把一个大的部分拆成几个小的部分来看,再由小的组合成大的,这题中把他想象求黄色区域面积。黄色区域左上角的坐标为(x1,y1)右下角的坐标为(x2,y2),求这两个坐标围城面积
其中每一块代表一个元素值。
在这里插入图片描述
计算面积(所围部分的和)公式:在这里插入图片描述
说明: S[x2][y2]代表(0,0)和(x2,y2)两个点所围成区域的和(或面积),因为两个区域重合部分减了两次。所以还要再加一次重合部分的面积。

三、代码

注意: 在本段代码里面,因为存在i-1和y-1等计算式,所以把数组的第一行和第一列都设置成0不赋值,虽然有点内存的浪费,但是相对于提高了程序的运行速度来说,利大于弊。

#include<cstdio>
#include<iostream>
using namespace std;
const int N = 1010;
int arr[N][N];
int S[N][N];						//前缀数组
//求子矩阵的和
int main() {

	int n, m, q;		//n行m列,查询q次
	printf("请输入行数n和列数m\t");
	scanf("%d%d%d", &n, &m, &q);
	printf("请输入数组值,建议一行一行的输入,数字和数字之间打空格\n");
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%d", &arr[i][j]);
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			S[i][j] = arr[i][j] + S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1];
		}
	}
	while (q--) {
		int x1, x2, y1, y2; //所选区域的两个点
		printf("请输入两个点坐标:\n");
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		int sum = S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1];
		printf("选定区域的和为:%d\n", sum);
	}
	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值