码迷,mamicode.com
首页 > 编程语言 > 详细

编程之美——字数组之和的最大值(二维,动态规划)

时间:2015-07-16 13:19:47      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

把前一个问题扩展了一下,寻找二维数组中,从(x1, y1)到(x2, y2)确定的矩形区域的数据之和最大值。

解法一给出了一个技巧,建立一个和原数组一样大的数组,用来保存(0, 0)到(x, y)的和,即P[x][y] = sum(x[0][0] –> x[x][y])。然后用Sum = PS[i_max][j_max]  - PS[i_min - 1][j_max] – PS[i_max][j_min - 1] + PS[i_min - 1][i_min -1]。不知道书上为什么要让数组从1开始,然后把数组的边界置0。

解法二用了分治的思想,或者动态规划吧。先假定一个边界,用穷举遍历这些边界,再把选定的数据变换为一维数据,根据上一节的算法进行分析。

扩展问题:

1. 收尾相连后,就只能上下确定边界,然后按照一维的解法进行求解。

2. 上下也相连,就要两个方向都按照首尾相邻的情况考虑了。

3、4. 三维和四维的情况,至少可以先在两个方向上遍历,在另一方向上上先求和再按一维情况求解吧。

1. 简述

    给定一个n*n(0<n<=100)的矩阵,请找到此矩阵的一个子矩阵,并且此子矩阵的各个元素的和最大,输出这个最大的值。
    Example:
     0 -2 -7  0 
     9  2 -6  2 
    -4  1 -4  1 
    -1  8  0 -2 
    最大子矩阵为:
    9 2 
   -4 1 
   -1 8

2. 原理

    最大子矩阵和是最大子序列和的二维扩展。
    穷举所有子矩阵的话,有C(n,2)*C(n*2)/2个子矩阵,就是n^4个子矩阵,这还不算每个子矩阵求和的时间,就到了O(n^4)。
    转化为最大子序列求解的思路是:固定第i列到第j列的范围,寻找在这个范围内的最大子矩阵,这个寻找过程,把每行第i列上的元素到第j列的元素分别求和,就转变为了一维的情况。由于有C(n,2)种列的组合,而求一维的子序列需要n的时间,所以,总体上时间复杂度为O(n^3)。

3. 递推公式

    A的下标从0开始,为了增加哨兵,F,P,Q的下标都从1开始。    
    · A[N][N]表示输入矩阵。
    · F[N+1][N+1],F[i][j]表示从第i行的第0列到第j列的元素和。
    F[i][j]=0,j=0
      F[i][j]=A[i-1][j-1], j=1
      F[i][j]=F[i][j-1]+A[i-1][j-1],j>1
      这样当固定第i列到第j列的时候,转化为一维数组的第k个元素就可以表示为F[K][j]-F[K][i-1],K是行下标,i和j都是列下标,由于矩阵的统计是从1开始的,所以i,j,k都是大于等于1的,即i-1不会下标越界,这就是前面哨兵的作用。
    固定i列和j列的时候的求解递推公式:
    · P[N+1],P[k]表示固定第i列到第j列时,从第1行到第k行范围内,包括第k行的最大子矩阵。
    · Q[N+1],Q[k]表示固定第i列到第j列时,从第1行到第k行范围内,最大子矩阵。
      P[k]=F[0][j]-F[0][i-1], k=1
      P[k]=P[k-1]>0?(P[k-1]+F[k][j]-F[k][i-1]):(F[k][j]-F[k][i-1]),k>1
      Q[k]=P[k], k=1
      Q[k]=max{Q[k-1], P[k]}, k>1
      Q[N]即为固定列(i-j)范围内的最大和。

#include<iostream>
#include<vector>
#include<math.h>
using namespace std;

//

int Maxval_temp(int* a,int n)
{
	if(n==1)
		return a[n-1];
	int maxall=a[n-1];
	int maxstart=a[n-1];
	for(int i=n-2;i>=0;i--)
	{
		maxstart=max(a[i],a[i]+maxstart);
		maxall=max(maxall,maxstart);
	}
	return maxall;
}

int MaxVal(vector<vector<int>> vec)
{
	if(vec.empty())
		return 0;
	int m,n;
	m=vec.size();
	n=vec[0].size();
	if(m==1)
		return vec[0][0];
	int max_val=vec[0][0];
	for(int i=0;i<m;i++)
		for(int j=i;j<m;j++)
		{
			int* ptr=new int[n];
			for(int k=0;k<n;k++)
			{
				int temp1=0;
				for(int g=i;g<j;g++)
					temp1+=vec[k][g];
				ptr[k]=temp1;
			}
			int temp_max=Maxval_temp(ptr,n);
			if(temp_max>max_val)
				max_val=temp_max;
		}
	return max_val;
}

int main()
{


}

  

编程之美——字数组之和的最大值(二维,动态规划)

标签:

原文地址:http://www.cnblogs.com/yanliang12138/p/4650712.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!