PAT甲级A1007---动态规划最大连续子序列和

1007 Maximum Subsequence Sum (25分)

1007.png
分析:

本题要求最大连续子序列的和,输出最大之和以及子序列第一个数和最后一个数。如果方案不唯一,则输出i,j最小的一组。如果所有数都是负数,则最大和为0,然后输出首尾元素。
先考虑如何求最大和。以dp[i]表示以A[i]作为末尾的连续序列最大和。以本题为样例dp[0]=-10,dp[1]=1,dp[2]=3......容易知状态转移方程为dp[i]=max{A[i],dp[i-1]+A[i]}。通过遍历就可通过dp[0]把所有dp求出来,最大和就是dp数组中最大的数。
再考虑如何求最大连续子序列的首位元素,以s[i]表示以A[i]作为结尾的最大连续子序列是从哪个元素开始,根据状态转移方程易知s[i]=i或者s[i]=s[i-1]。
在一开始的时候先考虑所有数是负数的情况,节省时间。

C++:
#include <cstdio>

const int maxn = 10010;

int arr[maxn], dp[maxn], s[maxn];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    //先处理全为负数的情况
    bool flag = false; //是否有正数
    for (int i = 0; i < n; i++) {
        if (arr[i] >= 0) {
            flag = true;
            break;
        }
    }
    if (flag == false) {
        printf("0 %d %d\n", arr[0], arr[n - 1]);
        return 0;
    }
    dp[0] = arr[0];
    s[0] = 0;
    for (int i = 1; i < n; i++) {
        if (dp[i - 1] + arr[i] > arr[i]) {
            dp[i] = dp[i - 1] + arr[i];
            s[i] = s[i - 1];
        } else {
            dp[i] = arr[i];
            s[i] = i;
        }
    }
    int index = 0;//dp数组最大值的下标
    for (int i = 1; i < n; i++) {
        if (dp[i] > dp[index]) {
            index = i;
        }
    }
    printf("%d %d %d\n", dp[index], arr[s[index]], arr[index]);
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 动态规划 动态规划是一种高性能的牛逼算法,由美国的R.Bellman提出,它是动态就是体现在此算法是基于一个递推公...
    董泽平阅读 1,196评论 0 12
  • 动态规划(DP) 1.最大子序和(leetcode 53 S.) 给定一个整数数组 nums ,找到一个具有最大...
    不入大厂不改名阅读 919评论 0 2
  • 0. 动态规划分析 0.1 动态规划、递归和贪心算法的区别 动态规划就是利用分治思想和解决冗余的办法来处理问题,所...
    dreamsfuture阅读 7,485评论 2 6
  • 1.01背包 题目描述 有 n 个重量个价值分别为 w_i, v_i 的物品。从这些物品中选出总重量不超过 W 的...
    一只可爱的柠檬树阅读 451评论 0 2
  • LeetCode基础算法-动态规划 LeetCode 动态规划 动态规划的核心步骤: 查看大问题的最优解能否使用小...
    24K男阅读 1,650评论 0 3