[PAT-Advanced] A1007 Maximum Subsequence Sum (25)

本文详细解析了PAT甲级A1007题目——寻找连续子序列中和最大的算法实现。通过动态规划方法,文章提供了C++代码示例,展示了如何找到具有最大和的连续子序列及其边界元素。

总题解目录

[PAT- Advanced Level] 甲级题解目录(Advanced Level)

A1007 Maximum Subsequence Sum (25point(s))

Given a sequence of K integers { N​1​​ , N​2​​ , …, N​K​​ }. A continuous subsequence is defined to be { N​i​​ , N​i+1​​ , …, N​j​​ } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4

Analysis

  • 求最长子序列和。如果输入全为负数,则结果要求输出的和为0,并输出整个数组的首尾数据。
  • 使用DP思想。只要所有dp的值都是负数,就可以肯定整个数组中的数据都是负数。
  • 注意读题,最后输出的是对应位置数据的值,而不是位置!

C++ Code

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string.h>
#define MAX_K 100000

using namespace std;


int main(){
    int k, end_index = 0, max_sum=-1;	// max_sum设置为-1非常关键,若设置为0,过不了测试点5(例:-2 0 0 0 -1)
    int max_subseq_sum[MAX_K];  // 存放到第i个位置为止的最大子序列和
    int start_idx[MAX_K];       // 用于存放到第i个位置为止的最大子序列的起始位置
    int data[MAX_K];            // 存放输入的数据
	memset(max_subseq_sum, 0, sizeof(max_subseq_sum));  // 数组初始置0

    cin >> k;

    for(int i = 0; i < k; i++){
        cin >> data[i];
        if(i == 0){
            max_subseq_sum[i] = data[i];
            start_idx[i] = i;
        }
        else{	// 到第i个位置为止的最大子序列和=max(data[i],max_subseq_sum[i-1]+data[i])
            if(data[i] > max_subseq_sum[i-1] + data[i]){	// data[i]较大时,i作为序列起始位置
                max_subseq_sum[i] = data[i];
                start_idx[i] = i;
            }
            else{	// max_subseq_sum[i-1]+data[i]较大时,起始位置与到i-1为止的最大子序列和的起始位置的相同
                max_subseq_sum[i] = max_subseq_sum[i-1] + data[i];
                start_idx[i] = start_idx[i-1];
            }
        }
        if(max_subseq_sum[i] > max_sum){    	// 找到最大值的结束位置
            max_sum = max_subseq_sum[i];
            end_index = i;
        }
    }

    if(max_subseq_sum[end_index] < 0)
        printf("0 %d %d", data[0], data[k-1]);
    else
        printf("%d %d %d", max_sum, data[start_idx[end_index]], data[end_index]);

	return 0;
}
CREATE TABLE [dbo].[T_GXJ_FD]( [datime] [nvarchar](14) NOT NULL, [A1001] [numeric](11, 3) NULL, [A1002] [numeric](11, 3) NULL, [A1003] [numeric](11, 3) NULL, [A1004] [numeric](11, 3) NULL, [A1005] [numeric](11, 3) NULL, [A1006] [numeric](11, 3) NULL, [A1007] [numeric](11, 3) NULL, [A1008] [numeric](11, 3) NULL, [A1009] [numeric](11, 3) NULL, [A1010] [numeric](11, 3) NULL, [A1011] [numeric](11, 3) NULL, CONSTRAINT [PK_T_GXJ_FD] PRIMARY KEY CLUSTERED ( [datime] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] 已知前面sqlserver数据库表格已经存在历史数据,例如T_GXJ_FD中,[datime]存储的是代表时间的字符串值:如20250930174948,其中20250930代表的是2025年9月30日,174948代表的是17点49分48秒,[A1001] [numeric](11, 3) NULL, [A1002] [numeric](11, 3) NULL, [A1003] [numeric](11, 3) NULL, [A1004] [numeric](11, 3) NULL, [A1005] [numeric](11, 3) NULL, [A1006] [numeric](11, 3) NULL, [A1007] [numeric](11, 3) NULL, [A1008] [numeric](11, 3) NULL, [A1009] [numeric](11, 3) NULL, [A1010] [numeric](11, 3) NULL, [A1011] [numeric](11, 3) NULL,分别为存储时刻[datime]所对应的值,这些值正常情况下是随时间是一直变大的,数据重新累计除外,表格T_GXJ_FD中的数据是5分钟就存入一组数据并更新一次的, 如何在SQLSERVER上建新表T_GXJ_FD_shift并编写代码,将datime时刻分为夜班,白班,日;[A1001]白班对应的值在数据不清零的情况下为白班最后时刻对应的值减去白班最初时刻对应的值即白班对应的最大值减去白班对应的最小值,当存在数据清零的情况下,白班最后时刻对应的值减去白班最初时刻对应的值为负数,此时应进行判断,将在白班期间的值进行分段,先计算清零前的最大值减去对应的最小值,再计算清零后的最大值减去对应的最小值,然后计算再相加作为白班值,同样夜班对应的值为夜班最后时刻对应的值减去夜班最初时刻对应的值即夜班对应的最大值减去夜班对应的最小值,当夜班存在数据清零的情况时,可能夜班最后时刻对应的值减去夜班最初时刻对应的值为负数,此时应进行判断,将在夜班期间的值进行分段,先计算清零前的最大值减去对应的最小值,再计算清零后的最大值减去对应的最小值,然后计算再相加作为夜班值。将白班与夜班所对应的值的和存在一个日值字段中,并将每月一日开始每日的值进行月累计单独存在一个字段中。[A1002]、[A1003]、[A1004]、[A1005]、[A1006]、[A1007]、[A1008]、[A1009]、[A1010]、[A1011]对应班次的值、日的值、月累计值获取与[A1001]的一致,新表T_GXJ_FDshift中的值随表T_GXJ_FD更新而更新,其中夜班、白班和日的区分规则为:假设今天为2025-09-25,则2025-09-25的夜班为datime所对应的:20250924200000至20250925075959;2025-09-25的白班为:20250925080000至20250925195959;日为20250924200000至20250925195900;请写出代码进行建表并处理,并将日期如2025-09-25存储为[date] NOT NULL格式,因为数据是不断更新的,所以对应的数据也在更新,如何在SQLSERVER中实现将表T_GXJ_FD的数据按夜班、白班、日和月累计存到新表中,并进行更新,请写出详细的流程,写出一个较好的具体流程就可以了,不要写出对比方案。注意,datime的格式为[datime] [nvarchar](14) NOT NULL,存储的内容样式为20250928054001,而在新表中,日期存储为[date] NOT NULL格式即2025-09-28。
10-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值