蓝桥求最大子矩阵和

动态规划

这种两端都是变化的问题是很难优化的,最好可以让一端固定,这样就会大大简化分析难度。于是将j暂时从原式子中提取出来,将剩下的命名为b[j]。

所以原问题就变成了这样。

根据b[j]的定义,b[j]是指以a[j]结尾的最大子段和。因此有如下公式:

b[j] = max{b[j - 1] + a[j] , a[j]}      1=

有了b[j],再对他取个极值,就可以得到原问题的解。

时间复杂度为O(n)

int maxSum(int[] a) {
    int res = 0;
    int b = 0;
    for (int i = 0; i < a.length; i++) {
        b = Math.max(b + a[i], a[i]);
        if (b > res) res = b;
    }
    return res;
}

这是求最大子矩阵和

#include
#include
#include
using namespace std;
#define maxn 510
int num[maxn][maxn];
int sum[maxn][maxn];
int dp_sum(int *a,int n)
{
	int ret=a[1],dp[maxn];
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++){
	dp[i]=max(a[i],dp[i-1]+a[i]);
	ret=max(dp[i],ret); 
	}
	return ret;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	memset(sum,0,sizeof(sum));
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		scanf("%d",&num[i][j]);
		sum[i][j]=sum[i-1][j]+num[i][j];
	}
	int maxnum=num[1][1];
	for(int i=1;i<=n;i++)
	for(int j=i;j<=n;j++)
	{
		int tem[maxn];
		memset(tem,0,sizeof(tem));
		for(int k=1;k<=m;k++)
		tem[k]=sum[j][k]-sum[i-1][k];
		maxnum=max(maxnum,dp_sum(tem,m));
	}
	printf("%d\n",maxnum);
}

你可能感兴趣的:(DP,acm)