算法导论之动态规划之最大子数组

来源:互联网 发布:christopher bu知乎 编辑:程序博客网 时间:2024/06/06 07:25
最大子串和问题
int MaxSum(int n,int *a){int sum=a[0],b=0;for(int i=0; i<n; i++){if(b>0){b+=a[i];}else{b=a[i];}if(b>sum){sum = b;}}return sum;}

将b认定为前面N个问题的最优解,

根据贪心原则来处理问题  max(b+a[i],a[i]);

不断的更新之前已经记录的连续最大值

-5 1 2 3 4 5 -50 1 2 20

可以根据这个测试用例来验证这个算法和思想


将一维数组升级为二位数组

求二位矩阵的最大子矩阵,代码如下

引用自南阳理工acm104

输入
第一行输入一个整数n(0<n<=100),表示有n组测试数据;
每组测试数据:
第一行有两个的整数r,c(0<r,c<=100),r、c分别代表矩阵的行和列;
随后有r行,每行有c个整数;
输出
输出矩阵的最大子矩阵的元素之和。
样例输入
14 40 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 
样例输出
15

#include<stdio.h>#define N 102int map[N][N]={0};int getMax(int (*a)[N],int n,int (*b)[N]){    int i,sum=a[0][1]-b[0][1],t=0;    for(i=1;i<=n;i++){        if(t>0)            t+=(*a)[i]-(*b)[i];        else            t=(*a)[i]-(*b)[i];        sum=t>sum?t:sum;    }    return sum;}int main(){    int m,n,p,i,j,k,max;    scanf("%d",&p);    while(p--){        scanf("%d%d",&m,&n);        for(i=1;i<=m;i++){            for(j=1;j<=n;j++){                scanf("%d",&map[i][j]);                map[i][j]+=map[i-1][j];            }        }        max = map[1][1];        for(i=1;i<=m;i++){            for(j=i;j<=m;j++){                k=getMax((int (*)[102])map[j],n,(int (*)[102])map[i-1]);                max=max>k?max:k;            }        }        printf("%d\n",max);    }}

        for(i=1;i<=m;i++){            for(j=1;j<=n;j++){                scanf("%d",&map[i][j]);                map[i][j]+=map[i-1][j];            }        }
这个循环是用了线段树的算法原理

i 到 j 的和等于  a[j]-a[i]

输入完成后,存储的就是每一列的值依次相加,将一行的每个数据看成是 0-i 行每一列的和;

用 换元的思想来认知某一行的数据,某一行的总和就是   矩阵 [0,0] 到 [i,j]的总和;

然后把求0到i行的最大子矩阵和看作求0-j 列的最大串和