题目
思路
利用动态规划,子问题就是以某个元素为结尾时,最大的子序列和;很明显,有n个子问题;
状态转移
当考察以某一元素结尾的子问题时,分为两种情况,以 前一个元素结尾的子问题值为负,那么以这个元素结尾的问题只有他自己;如果以 前一个元素结尾的子问题值为正,那么以这个元素结尾的问题就是加上他自己;最后跟全局的最大比较就可以
状态转移方程 dp[i] = max{A[i], dp[i-1]+A[i]}
知识
这道题让我明白了动态规划求解时,要搞明白是让你求最大子问题的最优解,还是所有子问题的最优解,如果是后者,就要保存一个全局最优解,每次求出来子问题最优解后就和全局比较,看是否需要更新全局
坑
测试点有一个元素的情况
代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int cnt;
cin >> cnt;
vector<int> dp(cnt,0);//dp数组用来存以这个元素为结尾时的最大连续子序列和
vector<int> startEle(cnt,0);//index数组用来存以这个元素为结尾时最大连续子序列的开始下标
int data,data1;
cin >> data;
//当输入是一个元素时,需要特殊处理
if(cnt == 1 ){
if(data > 0)
printf("%d %d %d",data,data,data);
else
printf("%d %d %d",0,data,data);
return 0;
}
data1 = data;//保存下来,以防最后都是负数
dp[0] = data;//将第一个元素作为当前最大值
startEle[0] = data;
int MaxRes = data, StartEle = 0, EndEle = 0;
for(int i=1; i<cnt; ++i){
cin >> data;
//如果以 前一个元素结尾的最大连续数组和为正数,直接加上这个元素,再跟全局最大比较
if(dp[i-1] > 0){
dp[i] = dp[i-1]+data;
startEle[i] = startEle[i-1];
}
//如果以 前一个元素结尾的最大连续数组和为负数,直接将这个元素作为临时最大,再跟全局最大比较
else if(dp[i-1] < 0){
dp[i] = data;
startEle[i] = data;
}
if(dp[i] > MaxRes){
StartEle = startEle[i];
EndEle = data;
MaxRes = dp[i];
}
}
if(MaxRes < 0)printf("%d %d %d",0,data1,dp[cnt-1]);
else printf("%d %d %d",MaxRes,StartEle,EndEle);
return 0;
}