PAT(甲级)1007 Maximum Subsequence Sum (25point(s))

题目

题目链接

思路

题目大意:给一个数组,找到最大的连续子序列;
状态划分:以每个元素为结尾划分状态,dp[i]代表以这个元素为结尾时最大的连续子序列和,注意状态dp[i]包含第i个元素;
状态转移:对于状态i来说,可分为两种情况:加上前一状态的结果,即如果 dp[i - 1] + num[i] >= num[i],则dp[i] = dp[i - 1] + num[i];只有自己本身, 则dp[i] = num[i];
最后遍历所有状态,找到最优;
对于题目中要求输出起点,则开一个数组start[i]保存以第i个元素结尾的最大连续子序列其开始下标,在进行分类讨论时更新start数组;
有可能元素全为负,需要在输入时就判断一下;
注意,不能令ans = -1; 因为最后比较时 -1 越界了,会导致答案错误;所以乖乖地在输入时判断是不是全为负,做特殊处理吧~~

代码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
#include <math.h>
#include <set>
#include <map>
using namespace std;
const int maxn = 1e4 + 10;

int dp[maxn], start[maxn], num[maxn], n;

int main()
{
     scanf("%d", &n);
     bool flag = false;
     for(int i = 0; i < n; i ++) {
          scanf("%d", &num[i]);
          if(num[i] >= 0) flag = true;
     }
     if(flag == false){
          printf("%d %d %d\n", 0, num[0], num[n - 1]);
          return 0;
     }
     //初始化状态
     dp[0] = num[0], start[0] = 0;
     //填充状态
     for(int i = 1; i < n; i ++){
          if(num[i] <= dp[i - 1] + num[i]){
               dp[i] = num[i] + dp[i - 1], start[i] = start[i - 1];
          }
          else {
               dp[i] = num[i], start[i] = i;
          }
     }
     //遍历所有情况,找出最大,ans记录结尾元素的下标
     int ans = 0;
     for(int i = 0; i < n; i ++){
          if(dp[i] > dp[ans]) ans = i;
     }
     printf("%d %d %d\n", dp[ans], num[start[ans]], num[ans]);

     system("pause");
     return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值