我们考虑一个$N\times M$的矩阵数据,若要对矩阵中的部分数据进行读取,比如求某个$a\times b$的子矩阵的元素和,通常我们可以想到$O(ab)$的遍历那个子矩阵,对它的各个元素进行求和。然而当$a$或$b$很大的时候,这样的计算显得太慢,如果要求子矩阵的最大元素和(如Ural 1146),更是简直慢到不能忍。

        于是就想,能不能在读入数据的同时,我就先进行一些预处理,使得到后面进行计算的时候,可以简化一些步骤呢?答案是可以的。
        我们开一个二维数组存放矩阵,第$0$行和第$0$列全都置$0$,真正的矩阵在数组中下标从$1$开始。
        通常对矩阵有两种预处理:
        一种是把矩阵拍扁,即把前一列或前一行加到后一列或后一行上:
按列压缩↑,紫色部分和=棕色部分和-橙色部分和
按行压缩↑,紫色部分和=棕色部分和-橙色部分和
        以按行压缩为例,读入当前元素$t=A_{ij}$后,我们令$B_{ij}=A_{ij}+B_{i-1,j}$,以此类推,当所有数据读入后,预处理即完成,$B_{ij}$表示对于矩阵$A$的第$j$列,从第1行到第$i$行的和。这样我们若想要知道矩阵$A$第$j$列上,从第$p$行到第$q$行的和,直接用$B_{qj}-B_{p-1,j}, (p\leq q)$一步求出,而不需要进行$q-p+1$步计算,那么从左上角$A_{ab}$到右下角$A_{pq}$的子矩阵元素和为$sum$$=$$\sum\limits_{i=a}^{p}\sum\limits_{j=b}^{q}$$A_{ij}$$=$$\sum\limits_{j=b}^{q}$$B_{pj}$$-$$\sum\limits_{j=b}^{q}$$B_{a-1,j}$大大减少了计算量,降低了时间复杂度。
        比较丑的示例代码:
 #include <stdio.h>
const int N=;
int matA[N][N], matB[N][N];
int main()
{
puts("Please input a matrix:");
for(int i=; i<N; i++)
for(int j=; j<N; j++) {
scanf("%d", matA[i]+j);
matB[i][j]=matB[i-][j]+matA[i][j];
}
puts("The Preprocessed matrix is:");
for(int i=; i<N; i++)
for(int j=; j<N; j++)
printf("%d%c", matB[i][j], j==N-?'\n':' '); int a, b, p, q, res;
while(puts("Please input a, b and p, q:"),
~scanf("%d%d%d%d", &a, &b, &p, &q) )
{
res=;
puts("Sum from A_ab to A_pq is:");
for(int j=b; j<=q; j++)
res+=matB[p][j]-matB[a-][j];
printf("%d\n\n", res);
}
return ;
}
        运行结果:
 
       而另一种则是压缩到一个元素上,用$B_{ij}$表示从最左上角元素$A_{11}$到元素$A_{ij}$的和$\sum\limits_{m=1}^{i}\sum\limits_{n=1}^{j}$$A_{mn}$$, $$(i \geq 1, j \geq 1)$:
读入预处理↑,右图紫色块=4+24+30-18=40
        为了保持这一性质,我们在读入当前元素$t=A_{ij}$后,令$B_{ij}$$=$$A_{ij}$$+$$B_{i,j-1}$$+$$B_{i-1,j}$$-$$B_{i-1,j-1}$。当所有数据读入后,预处理即完成。
计算区域和↑,紫色区域和=60-12-15+3=36
        此时我们若想要求出从左上角$A_{ab}$到右下角$A_{pq}$的子矩阵元素和,只需三步计算:$sum$$=$$\sum\limits_{i=a}^{p}\sum\limits_{j=b}^{q}$$A_{ij}$$=$$B_{pq}$$-$$B_{p,b-1}$$-$$B_{a-1,q}$$+$$B_{a-1,b-1}$,即可使时间复杂度降低到常数。
        比较丑的示例代码:
 #include <stdio.h>
const int N=;
int matA[N][N], matB[N][N];
int main()
{
puts("Please input a matrix:");
for(int i=; i<N; i++)
for(int j=; j<N; j++) {
scanf("%d", matA[i]+j);
matB[i][j]=matA[i][j]+matB[i][j-]+matB[i-][j]-matB[i-][j-];
}
puts("The Preprocessed matrix is:");
for(int i=; i<N; i++)
for(int j=; j<N; j++)
printf("%3d%c", matB[i][j], j==N-?'\n':' '); int a, b, p, q, res;
while(puts("Please input a, b and p, q:"),
~scanf("%d%d%d%d", &a, &b, &p, &q) )
{
puts("Sum from A_ab to A_pq is:");
res=matB[p][q]-matB[p][b-]-matB[a-][q]+matB[a-][b-];
printf("%d\n\n", res);
}
return ;
}
        运行结果:

ACM 中 矩阵数据的预处理 && 求子矩阵元素和问题的更多相关文章

  1. 矩阵快速幂在ACM中的应用

    矩阵快速幂在ACM中的应用 16计算机2黄睿博 首发于个人博客http://www.cnblogs.com/BobHuang/ 作为一个acmer,矩阵在这个算法竞赛中还是蛮多的,一个优秀的算法可以影 ...

  2. 市场清仓价格算法 python求矩阵不同行不同列元素和的最大值

    问题描述 求矩阵不同行不同列元素和的最大值(最小值) 问题求解 1.通过scipy库求解 scipy.optimize库中的linear_sum_assignment方法可以求解 输入一个矩阵,参数m ...

  3. 关于 矩阵在ACM中的应用

    关于矩阵在ACM中的应用 1.矩阵运算法则 重点说说矩阵与矩阵的乘法,不说加减法. 支持: 结合律  (AB)C = A(BC) 分配律 A(B+C) = AB + AB $\left( \lambd ...

  4. Matlab中矩阵的平方和矩阵中每个元素的平方介绍

    该文章讲述了Matlab中矩阵的平方和矩阵中每个元素的平方介绍.   设t = [2 4 2 4] 则>> t.^2 ans = 4 164 16 而>> t^2 ans = ...

  5. C语言:将ss所指字符串中所有下标为奇数位置的字母转换为大写-将该字符串中的所有字符按ASCII码值升序排序后输出。-将a所指的4*3矩阵第k行的元素与第0行元素交换。

    //函数fun:将ss所指字符串中所有下标为奇数位置的字母转换为大写,若不是字母,则不转换. #include<conio.h> #include<stdio.h> #incl ...

  6. matlab中矩阵的表示与简单操作

    原文地址为:matlab矩阵的表示和简单操作 一.矩阵的表示在MATLAB中创建矩阵有以下规则: a.矩阵元素必须在”[ ]”内: b.矩阵的同行元素之间用空格(或”,”)隔开: c.矩阵的行与行之间 ...

  7. Java在ACM中的应用

    Java在ACM中的应用 —. 在java中的基本头文件(java中叫包) import java.io.*; import java.util.*; //输入Scanner import java. ...

  8. stl 在 acm中的应用总结

    总结一些在acm中常用的小技巧,小函数 之前尝试着总结过很多次.都失败了,因为总是担心不全,理解的也不是很透彻.这次再来一次...其实之前保存了很多的草稿就不发布了,当然,下面说的很不全面,路过的大牛 ...

  9. Python numpy中矩阵的用法总结

    关于Python Numpy库基础知识请参考博文:https://www.cnblogs.com/wj-1314/p/9722794.html Python矩阵的基本用法 mat()函数将目标数据的类 ...

随机推荐

  1. 透视 HTML子元素的margin-top样式会应用在父元素上的原由

    情况说明 当对页面中元素设置margin-top样式时,如果该元素有父元素,则margin-top会应用与父元素,子元素的top与父元素的top重叠.举例说明 <style>body{ma ...

  2. cookies如何成为全局变量以及设置,删除,获取

    (一)cookie机制将信息存储于用户硬盘,因此可以作为全局变量 (1)保存用户登录状态.例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供 ...

  3. React.js实现原生js拖拽效果及思考

    一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...

  4. Hadoop入门学习笔记---part3

    2015年元旦,好好学习,天天向上.良好的开端是成功的一半,任何学习都不能中断,只有坚持才会出结果.继续学习Hadoop.冰冻三尺,非一日之寒! 经过Hadoop的伪分布集群环境的搭建,基本对Hado ...

  5. js实现StringBuffer

    实现 function StringBuffer() { this.__strings__ = []; }; StringBuffer.prototype.Append = function (str ...

  6. 基于 HTML5 的 WebGL 技术构建 3D 场景(一)

    今天和大家分享的是 3D 系列之 3D 预定义模型. HT for Web 提供了多种基础类型供用户建模使用,不同于传统的 3D 建模方式,HT 的建模核心都是基于 API 的接口方式,通过 HT 预 ...

  7. asp.net core 依赖注入问题

    最近.net core可以跨平台了,这是一个伟大的事情,为了可以赶上两年以后的跨平台部署大潮,我也加入到了学习之列.今天研究的是依赖注入,但是我发现一个问题,困扰我很久,现在我贴出来,希望可以有人帮忙 ...

  8. Eclipse代码和xml文件的智能提示

    一.代码智能提示 Windows → Preferences → Java→ Editor → Content Assist 将 Auto activation delay(ms): 改为 0 将 A ...

  9. Spring在web应用中获得Bean的方法

    一:使用ApplicationContext获得Bean 首先新建一个类,该类必须实现ApplicationContextAware接口,改接口有一个方法,public void setApplica ...

  10. 《Web开发过滤Javascript、HTML的方法》

    JavaScript过滤方法: 第一种方案:使用 htmlspecialchars 函数转换特殊字符和使用 nl2br 函数插入一些必要的 <br /> 标签. $comment = &l ...