链接:coed force
中文链接:洛谷P5124
题目大意:
FJ想要给他的朋友送礼物,但是他不太会包装礼物,所以他把这个任务交给他的N(1<= N <= 104)奶牛们去完成。奶牛们排成一行依次编号为1…N,第i头奶牛的水平为si,它们的技能水平可能参差不齐,所以FJ打算给他的奶牛们分组,每一组可以有任意K(1<= K <= 103)头连续的奶牛,一头奶牛只能在一个组里面(可以自己一头牛一组)。由于奶牛们会互相学习,这一组中每一头奶牛的技能水平会变成这一组中水平最高的奶牛的技能水平。
请你求出最佳的分组方案下奶牛们可以达到技能之和的最大值。
数据大小:
如题意所示。
思路:
这题是一个dp题,设dp[i]表示当前水平之和的最大值。
有 :dp[i] = max(dp[j] + (i−j) ∗ max(a[j]))
其中 (max(0,i−k) ≤ j < i)(转移方程是dl推的%%%)
根据题目意思,每头奶牛可以自己成为一个组,也可以和连续的包括自己在内的不超过K头奶牛组成一组,假设k = 3,对于第i个奶牛,有
k = 1
k = 2
k = 3
但是对于i前面的来说,可以知道没有重复的部分是
对于每一个奶牛,我们只需要往后更新就行,不用理前面的部分,其组队的情况都包含在前面 i-k ~ i+k 个内了,只要每种情况最优就好了
其实我也还不太懂,讲的有点玄乎,见谅(lll¬ω¬)。
ac代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
#define MAX 10005
int dp[MAX];
int a[MAX];
int main()
{
int n,k;
scanf("%d %d",&n,&k);
for(int i = 1;i<=n;i++)
scanf("%d",&a[i]);
for(int i = 1;i<=n;i++)
{
int temp_max = 0;
for(int j = i;j<min(i+k,n+1);j++)//第i个数
{
if(a[j]>temp_max)
temp_max = a[j];
if(dp[j] < dp[i-1]+(j-i+1)*temp_max)//往后更新
dp[j] = dp[i-1]+(j-i+1)*temp_max;
}
}
printf("%d",dp[n]);
return 0;
}