原题目链接HDU1231
分类
HDU 动态规划 最大连续子序列
题意
(dp初步)
求最大子序列和,并且要求记录该子序列的开头数字以及结束数字(其实这样一来就可以得到整个序列了)
样例输入输出
Sample Input
6
-2 11 -4 13 -5 -2
10
-10 1 2 3 4 -5 -23 3 7 -21
6
5 -8 3 2 5 0
1
10
3
-1 -5 -2
3
-1 0 -2
0
Sample Output
20 11 13
10 1 4
10 3 5
10 10 10
0 -1 -2
0 0 0
想法
这题是在最基础的最大子序列和的基础上进行了一点点小的修改,我们都知道,对于最原始的最大子序列和问题有一个函数模板,大致思想如下:
//两种方法初始值不同
//第一种
cnt = 0;
for(int i=0;i<n;i++)//n输入序列的长度
{
if(cnt<0)cnt = 0;//cnt为记录当前序列和的变量
else cnt+=num[i];//num数组为输入的序列
if(cnt>maxx)maxx = cnt;//maxx用来保存最大序列和
}
//第二种
sum = -11111;
for(int i=0;i<k;i++){//k输入序列的长度
if(sum<0){
sum = num[i];
}
else sum+=num[i];
if(sum>MAX){
MAX = sum;
}
}
而对于本题,有两个注意点,第一是需要记录起始位置和结束为止,第二是题目提到可能会存在全部为负数的序列,对于这种序列,则认为最大序列和为0,并且起始位置是num[0],而结束位置是num[n-1]
代码
124ms
#include<bits/stdc++.h>
const int maxn = 11111;
using namespace std;
int num[maxn];
int main(){
int k;
while(~scanf("%d",&k) && k){
int sum = -1111;
int MAX = -1111;
int temp,head,tail;
bool flag = false;
for(int i=0;i<k;i++){
scanf("%d",&num[i]);
if(num[i]>=0) flag = true;
}
for(int i=0;i<k;i++){
if(sum<0){
sum = num[i];
temp = num[i];
}
else{
sum+= num[i];
}
if(sum>MAX){
head = temp;
tail = num[i];
MAX = sum;
}
}
if(flag) printf("%d %d %d\n",MAX,head,tail);
else printf("%d %d %d\n",0,num[0],num[k-1]);
}
}