最大值子区间和的一维二维问题

一维问题:nyoj 44 子串和

链接:click here

题目大意:给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。

思路:m是元素总个数,sum是第一个元素,将当前的第一个元素作为最大值max,之后依次输入,检查sum<0?是的话更新sum为当前输入值:否则累加,最后比较这样每次步骤的最大值。

代码:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
int main()
{
    int n,m,q,max,sum;
    scanf("%d",&n);
    while(n--)
    {
        max=0;
        scanf("%d",&m);
        scanf("%d",&sum);
        max=sum;
        while(m--)
        {
            scanf("%d",&q);
            if(sum<0) sum=q;
            else sum+=q;
            if(sum>max) max=sum;
        }
        printf("%d\n",max);
    }
    return 0;
}

二维问题:nyoj 104 最大和

链接:click here

题目大意:

给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。

例子:

0 -2 -7 0

9 2 -6 2

-4 1 -4 1

-1 8 0 -2

其最大子矩阵为:

9 2

-4 1

-1 8

其元素总和为15。

思路:

二维的问题,其实可以转化为一维的问题。

首先我们要注意到二维子矩阵在选取的时候是个矩阵,联系一个我们经常会用到的技巧:需要频繁计算一个数据任意一个区间的和的时候,我们会预先把这个数组使用mapp[i]=mapp[i]+mapp[i-1]的方式把它记录的值变为数组到这个位置的和,这样的好处就是任意一个区间[i,j]的和就可转化为了mapp[i]-mapp[j-1]。在这里我们依然采用这样的技巧。我们把这个矩阵记录的值对于每个列向量都做上述改变。

然后我们就发现,但我们选取任意的连续行进行组合的时候,这个行区间对于的列的值的和都可以用上述方法快速获得,那么对于每个列的和又会变为一个求一维连续区间最大和问题了。到此这个问题就可以以O(n^2)的复杂度解决了。

代码:

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const int maxn=102;
int mapp[maxn][maxn];
#define mem(a,b) memset(a,b,sizeof(a))
int main()
{
    int i,j,k,tt,T,r,c,max,temp;
    scanf("%d",&T);
    while(T--)
    {
        mem(mapp,0);
        scanf("%d%d",&r,&c);
        for(i=1; i<=r; i++)
        {
            for(j=0; j<c; j++)
            {
                scanf("%d",&mapp[i][j]);
                mapp[i][j]+=mapp[i-1][j];
            }
        }
        for(i=1,tt=mapp[1][0]; i<=r; i++)
            for(j=i; j<=r; j++)
            {
                for(k=max=0; k<c; k++)
                {
                    temp=mapp[j][k]-mapp[i-1][k];
                    max=(max>=0?max:0)+temp;
                    tt=max>tt?max:tt;
                }
            }
        printf("%d\n",tt);
    }
    return 0;
}
时间: 2024-10-27 08:04:22

最大值子区间和的一维二维问题的相关文章

c++ 依据输入动态声明数组(一维,二维)

较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #include <stdio.h> #include <stdlib.h> int main() { int a; int i; scanf("%d",&a); int c[a]; for( i =0 ;i<a;i++) scanf("%d",

[blog 机器视觉]一维二维码的提取、识别和产生

一维二维码的提取.识别和产生 零.相关说明: 在"jsxyhelu.cnblogs.com/机器视觉"栏目主要介绍和图像处理和机器视觉相关的的成套的解决方案.思路和软件集.希望能够为大家在实际工作中解决具体问题提供一些帮助. 一.背景资料: 现在一维码.二维码广泛使用于工业各方面.很多和图像处理相关的需求也有所涉及.这里也看过一些论文,里面有一些方法还是art-of-air的,也有一些具备一定参考价值.这里只是谈一谈一般情况下的提取和识别.对于特殊情况,肯定要特殊对待,其实本身是一个增

稳定排序nlogn之归并排序_一维,二维

稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)) ],冒泡排序(n^2),插入排序(n^2),交换排序(n^2),计数排序[n为数字个数,k为数字范围,O(n+k)]等. Problem:对n个数进行排序,n<=100000,1s以内 正常来说我们都用qsort(c),sort(c++),但快速排序平均时间复杂度为nlogn,最坏时间复杂度为n^

【树状数组】树状数组一维二维模板

以下模板都是点更新,区间查询,如果是区间更新点查询,只需将利用lowbit的循环方向倒过来 一维: inline int lowbit(int x) { return x & -x; } void add(int x, int val) { for(int i = x; i <= n; i += lowbit(i)) C[i] += val; } int sum(int x) { int ret = 0; for(int i = x; i > 0; i -= lowbit(i)) re

一维 + 二维树状数组 + 单点更新 + 区间更新 详解

树状数组详解: 假设一维数组为A[i](i=1,2,...n),则与它对应的树状数组C[i](i=1,2,...n)是这样定义的: C1 = A1 C2 = A1 + A2 C3 = A3 C4 = A1 + A2 + A3 + A4 C5 = A5 C6 = A5 + A6 ................. C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 ................ 如图可知: 为奇数的时候他是代表他本身,而为偶数的时候则是代表着自

C# 链表去重 List 一维 二维 分别使用 Distinct() GroupBy() 方法

分别使用过List中Distinct(),GroupBy()实现链表的去重. 1.先上效果: 一维链表中分别有元素"aa","bb",'aa','aa',"cc",使用Distinct()方法后输出 aa,bb,cc 二维链表中类型为ClassA类型,其中对象的属性A分别为1,1,2,3,1,使用GroupBy()方法实则是分类,输出Key值分别为1,2,3. 2.上代码,类ClassA 1 class ClassA 2 { 3 private

资瓷区间修改+区间求和的树状数组(一维/二维)

一维:令 \(v_i\) 为差分数组,那么 \([0, k]\) 的前缀和就是 \(\sum{v_i(k+1-i)} = (k+1) \cdot \sum{v_i} + \sum{v_i \cdot (-i)}\),树状数组维护一下 \(v_i\) 和 \(v_i \cdot i\) 即可. template <typename I> struct Fenwick { struct Node { I v0, v1; void add(I d0, I d1) { v0 += d0; v1 +=

2.15 子数组之和的最大值(二维)

题目:给定一个二维数组,求这个二维数组的子数组之和的最大值. 分析:将二维降低到一维的情况. 代码: #include <iostream> const int MAXN = 10000; const int INF = 100000000; using namespace std; int B[MAXN][MAXN], PS[MAXN][MAXN]; int n, m; int BC(int first, int last, int liehao) { return PS[last][lie

二维数组求子数组之和最大值(首尾相接, 圆柱)

问题:求二维数组的子数组之和的最大值(首尾相接,即形成圆柱) 成员: 陈晨:负责代码复审和代码测试计划 王颖瑞:负责程序分析,代码编程 思路:对于这个问题,我们可以结合之前的实验(二维数组求子数组之和的最大值和首尾相连一维数组的子数组之和的最大值),把为二维数组的列扩大二倍,之后想一维数组(首尾相连)一样,把二维数组分成不同的几个二维数组.之后就分开求不同的二维数组的子数组的最大值,最后之间比较,求出总的最大值. 代码: #include<iostream> using namespace s