动态规划

来源:互联网 发布:js函数传递对象参数 编辑:程序博客网 时间:2024/06/14 23:52

最大子段和

题目

给定一个长度为n的一维数组a,请找出此数组的一个子数组,使得此子数组的和sum=a[i]+a[i+1]+……+a[j]最大
例如
31 -41 59 26 -53 58 97 -93 -23 84
子矩阵59+26-53+58+97=187为所求的最大子数组。

解法

1 直接穷举

int max = 0;for(int i = 0; i < n; i ++){    for(int j = i; j < n; j ++)    {        int sum = 0;        for(int k = i; k <= j; k ++)            sum += a[k];        if(sum > max)            max = sum;    }}

2 递推(复杂度o(n^2))
首先生成从0到i的和sum[0],sum[1]…sum[n-1],然后只需要相减即可,比如1-2的线段和为sum[2]-sum[0]。

3 动态规划
用b[n]表示,以a[n]结束的最大子段和,b[n] = max(b[n-1]+a[n],a[n]),则整体的最大子段和为max(b[j])

int max = 0;int b[n];b[0] = a[0];for(int i = 1; i < n; i ++){    b[i] = max(b[i-1]+a[i], a[i]);    if(b[i] > max)        max = b[i];}

最大子矩阵和

题目

给定一个m行n列的整数矩阵A,试求A的一个子矩阵,使其各元素之和为最大。

解法

假设matrix(i,j)代表第i行到第j行的矩阵的最大子矩阵的和,那么最大的元素之和为max(matrix(i,j)),那么我们只需要求matrix(i,j),matrix(i,j)的元素依次为[[a[i][0],a[i][1]…a[i][n-1]],…,[a[j][0],a[j][1]…a[j][n-1]],可以看到每一列的元素是固定的,那么我们可以将每一列的元素相加,这样就可以利用最长子线段和来求解这一问题。

代码

class Solution {public:    int kk;    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {        int h = matrix.size();        int w = matrix[0].size();        kk = k;        int maxs = -100000;        for(int i = 0; i < h; i ++)        {            vector<int> num(w,0);            for(int j = i; j < h; j ++)            {                 for(int x = 0; x < w; x ++)                {                        num[x] += matrix[j][x];                 }                int tempsum = maxsum(num);                maxs = max(maxs, tempsum);            }        }        return maxs;    }    int maxsum(vector<int> a)    {        int maxn = 0;        int b = a[0];        for(int i = 1; i < a.size(); i ++)        {            if(b+a[i] < k && b <= k)            b = max(b+a[i], a[i]);            if(b > maxn)                maxn = b;        }        return maxn;    }};