前言:今天看了看例题,渣渣想说有点儿看不懂,emmmm,我来记录一下自己看得比较透彻的题目好啦…
1.最大子段和问题:
题目描述:给定 N (1 <= N <= 100000) 个绝对值不大于 1000 的整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[N],求从该序列中取出连续一个子段,使这个子段的和最大。如果某子序列全是负数则定义该子段和为0。求 max{0,a[i]+a[i+1]+…+a[j]}, (1 <= i<= j <= N)
输入:有一个正整数 N,后面紧跟 N 个绝对值不大于 1000 的整数
输出:最大子段和
样例输入:
5 6 -1 5 4 -7
样例输出:
14
样例分析:所选子段为(6 -1 5 4)即可得到结果14.
状态设计:
dp[i] (1 <= i <= N) 表示以 a[i] 结尾的最大连续子段和。
显然,dp[i] >= 0 (1 <= i <= N)
求解目标:
max{dp[i]} (1 <= i <= N)
状态转移方程:
dp[i] = max{a[i],0} (i = 1)
dp[i] = max{dp[i-1] + a[i], 0} (2 <= i <= N)
代码实现:
变量定义:
int N;
int a[SIZE];
int dp[SIZE];
状态转移过程:
int maxSubSum = 0;
dp[1] = Max(a[1], 0);
int i;
for (i = 2; i <= N; ++i)
dp[i] = Max(dp[i - 1] + a[i], 0);
for (i = 1; i <= N; ++i)
{
if (maxSubSum < dp[i])
maxSubSum = dp[i];
}
2.最大2子段和问题
题目描述:
给出n个整数: A={a1, a2,..., an}, 定义 d(A) 如下:
要求计算
d(A).
输入:第一行,整数
n(2<=n<=50000).
第二行包含n
个整数
a1, a2, ..., an.(|ai| <= 10000)
输出:每组测试数据输出一行,输出d(A)
的值
.
样例输入:
10
1 -1 2 2 3 -3 4 -4 5 -5
样例输出:
13
算法分析:若采用枚举法,其时间和空间复杂度可想而知。所以该题我们要借鉴最大子段和求出的结果。
状态设计:
dpL[i]
表示以
a[i] 结尾
的最大连续子段和。
dpL[i] = max{∑a[x..i], 0}
,
1 <= x <= i<= N
显然,dpL[i] >= 0 (1 <= i <= N)
dpR[i]
表示以
a[j] 开始
的最大连续子段和。
dpR[j] = max{∑a[j..y], 0}
,
1 <= j <= y<= N
显然,dpR[j] >= 0 (1 <= j <= N)
求解目标:max{max{dpL[k]} + max{dpR[l]}}
(
1 <= k < l<= N)
状态转移方程:
dpL[i] = max{a[i],0} (i = 1)
dpL[i] = max{dpL[i
–
1] + a[i], 0} (2<= i <= N)
dpR[j] = max{a[j],0} (j = N)
dpR[j] = max{dpR[j + 1] + a[j], 0}(1 <= j <= N-1)
3.最大子矩阵和
题目描述:给定
N (1 <= N <= 100)
和一个 N * N
的矩阵,求该矩阵的一个子矩阵,使得子矩阵中所有数字的和最大。求出这个最大值。
输入:一个整数 N
,然后是
N * N
个绝对值不超过 128
的整数
输出:只有一个值,最大子矩阵和
样例输入:
4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
样例输出:
15
算法分析:每次枚举子矩阵最上的行 u 和最下的行 d,再把这个子矩阵每一列的值相加,压缩成一个一维的数组,对这个数组求其最大子段和,这样就相当于把所有最上的行为u 并且最下的行为 d 的最大子矩阵和求出来了。
代码实现:
#include<bits/stdc++.h>
#define N 103
using namespace std;
int fun(int b[N],int n)
{
int i,max,c;
c=0;
max=0;
for(i=1;i<=n;i++)
{
if(c>0) c+=b[i];
else c=b[i];
if(max<c) max=c;
}
return max;
}
int main()
{
int i,j,n,max,sum,k;
int a[N][N],b[N];
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
max=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
b[j]=0;
for(j=i;j<=n;j++)
{
for(k=1;k<=n;k++)
b[k]+=a[j][k];
sum=fun(b,n);
if(max<sum) max=sum;
}
}
cout<<max<<endl;
return 0;
}