codefoces Teamwork

版权声明:博客作者为blue bear,严禁他人在未经作者同意下进行商用转载 https://blog.csdn.net/weixin_44354699/article/details/88377028

题面

For his favorite holiday, Farmer John wants to send presents to his friends. Since he isn’t very good at wrapping presents, he wants to enlist the help of his cows. As you might expect, cows are not much better at wrapping presents themselves, a lesson Farmer John is about to learn the hard way.

Farmer John’s N cows (1≤N≤104) are all standing in a row, conveniently numbered 1…N in order. Cow i has skill level si at wrapping presents. These skill levels might vary quite a bit, so FJ decides to combine his cows into teams. A team can consist of any consecutive set of up to K cows (1≤K≤103), and no cow can be part of more than one team. Since cows learn from each-other, the skill level of each cow on a team can be replaced by the skill level of the most-skilled cow on that team.

Please help FJ determine the highest possible sum of skill levels he can achieve by optimally forming teams.

Input
The first line of input contains N and K. The next N lines contain the skill levels of the N cows in the order in which they are standing. Each skill level is a positive integer at most 105.

Output
Please print the highest possible sum of skill levels FJ can achieve by grouping appropriate consecutive sets of cows into teams.

Note
In this example, the optimal solution is to group the first three cows and the last three cows, leaving the middle cow on a team by itself (remember that it is fine to have teams of size less than K). This effectively boosts the skill levels of the 7 cows to 15, 15, 15, 9, 10, 10, 10, which sums to 84.

样例

inputCopy
7 3
1
15
7
9
2
5
10
outputCopy
84

inputCopy
7 3
1
15
7
9
2
5
10
outputCopy
84

分析

给一个数列,让你分块,最多为K个数为一块,每一块的有一个数=最大值*区间个数,求分块后数的最大和。
一开始以为区间可以不连续就排序贪心,wa了。发现区间要连续,也就是不能动这个区间,于是使用dp。
dp[i]指的是前i个的最大和。
遍历每个i 对于个i选取本身到k个数的值去更新dp
则dp[i]=dp[i-1]+后面区间的数。
则有dp[i+j]=max(dp[i+j],dp[i-1]+(j+1)*maxn);
其中maxn为当前区间最大值。

比如4,5,3,6; k=3
一开始是4,开始遍历,dp[1] (从一开始)=最大值区间个数=41=4
然后5继续dp[2]=最大值区间个数=52=10
然后5继续dp[3]=最大值区间个数=53=15(dp[0]是0所以没加上)
此时达到k,不往后。到下一个i
此时值为5,开始遍历dp[2]=dp[1]+最大值区间个数=4+51=9不比原来的10大,意思即4和5分别分块不如合起来的数更大一些,所以不更新,反之则更新
相信后面的你也会推断了…

代码

#include<bits/stdc++.h>
using namespace std;
int a[100005],dp[100005];
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 maxn=a[i];
		for(int j=0;j<k;j++){
			maxn=max(maxn,a[i+j]);
			dp[i+j]=max(dp[i+j],dp[i-1]+(j+1)*maxn);
		}
	}
	printf("%d\n",dp[n]);
} 

猜你喜欢

转载自blog.csdn.net/weixin_44354699/article/details/88377028