2018年长沙理工大学第十三届程序设计竞赛 - 数学考试

题目链接 数学考试


题意

今天qwb要参加一个数学考试,这套试卷一共有n道题,每道题qwb能获得的分数为ai,qwb并不打算把这些题全做完,
他想选总共2k道题来做,并且期望他能获得的分数尽可能的大,他准备选2个不连续的长度为k的区间,
即[L,L+1,L+2,….,L+k-1],[R,R+1,R+2,…,R+k-1](R >= L+k)。


思路

一开始我想的非常复杂,求完前缀和后要进行一系列的贪心操作,但是做到一半行不通,但是我发现了动态规划的做法,就是对于每个区间来说,都需要加上后面值最大的区间,那么我就先用一个dp数组从后往前扫,储存从最后一位到第i个区间的最大值。然后再从前往后扫输出最大值即可。


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int MAXN = (int) 2e5+7;
const ll INF = (ll) 0x3f3f3f3f3f3f3f3f;

int N,K;
ll A[MAXN];
ll Sum[MAXN];
ll dp[MAXN];  //存的是从后往前的最大值

int main()
{
    ios::sync_with_stdio(false);

    int T;
    cin >> T;
    while (T --){
        cin >> N >> K;

        for (int i = 1;i <= N;i ++) {
            cin >> A[i];
            Sum[i] = Sum[i-1] + A[i];
        }

        fill (dp,dp+MAXN,-INF);

        for (int i = N-K+1;i > 0;i --){
            dp[i] = max(dp[i+1],Sum[i+K-1]-Sum[i-1]);
        }

        ll mn = -INF;
        for (int i = 1;i+K-1 <= N;i ++){
            mn = max(mn,dp[i+K] + Sum[i+K-1]-Sum[i-1]);
        }
        cout << mn << endl;
    }
}
/*
3
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1
4 2
2 2 1 1
*/

猜你喜欢

转载自blog.csdn.net/qq_40513946/article/details/79943671
今日推荐