题目描述

  聪明的香穗子遇到难题了:一个序列上有n个整数,现在你要取m个,且这m个数的任意两个不能相隔太近,问能得到的数字和最大值是多少。

 

输入格式

  第一行三个数n,m,k,分别表示n个数,取m个,且m个中的任意两个位置差要大于等于k;

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

  第二行有n个整数,表示序列上的每个数。

 

输出格式

  一行,输出符合条件的最大和。

 

输入样例

4 2 2

3 4 -5 1

 

输出样例

5

 

题解

  容易想到我们设$f[i][j]$为选择$a[i]$且刚好选择了$j$个物品的最大值,那么容易得到$f[i][j] = a[i] + \underset{1 \leqslant l \leqslant i - k}{max} \left \{ f[l][j - 1] \right \}$。这时候发现会超时。

  这个时候我们改变$f[i][j]$的定义为选择$a[i]$且选择了不超过$j$个物品的最大值,那么就可以得到$f[i][j] = max\left\{f[i - 1][j], f[i - k][j - 1] + a[i]\right\}$

【题解】聪明伶俐的香穗子 随笔 第1张
#include <iostream>
#include <cstring>
#define MAXN 10001
#define MAXM 101

using namespace std;

int n, m, k;
int a[MAXN];
int f[MAXN][MAXM];

int main()
{
    cin >> n >> m >> k;
    memset(f, -128, sizeof f);
    for(register int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for(register int i = 1; i <= n; i++)
    {
        f[i][1] = max(f[i - 1][1], a[i]);
        for(register int j = 2; j <= m; j++)
        {
            if(i - k > 0) f[i][j] = max(f[i - 1][j], f[i - k][j - 1] + a[i]);
            else f[i][j] = f[i - 1][j];    
        }
    }
    cout << f[n][m];
    return 0;
}
参考程序

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄