2019 GDUT RC 1 Problem B(题解)

原题

题目大意

有n只母牛,每只母牛都有自己的技能水平si,然后你需要给这群母牛组队,组队的牛的编号必须是连续的,每个队的牛数不能超过k只。一个队伍里面所有牛的技能水平都会被队伍里最高技能水平代替。例如题目样例,把编号1,2,3,技能水平分别是1,15,7的牛组队后,这三只牛的技能水平就会变成15,15,15。题目要求让你组队后牛技能水平之和最大,并输出这个值。

题目分析

这道题可以用动态规划解决。设dp[i]为前i头牛组队后技能的最大和,初始化为0,递推式dp[i]=max(dp[i],dp[i-j]+max(s[i-j+1]→s[i])*j)(1<=j<=k),意思是dp[n](1<=n<i)已经求出,在求dp[i]时,可以先让第i头牛单独组一队,这时候j=1,这样dp[i]就等于dp[i-1]+s[i]*1。第二次尝试把第i头牛和第i-1头牛组队,这时候j=2,在保留这样算出来的dp[i]与上一次算出来的dp[i]中的较大值,也就是dp[i]=max(dp[i],dp[i-2]+max(s[i],s[i-1])*2),同理继续遍历直到j<=k,也就是基本把所有关于第i只牛的组队方案都尝试一遍,看看哪种方案最佳。这个过程需要注意的有在算dp[i]的过程中得保证i-j>0,也就是dp[i-j]存在,还有就是max(s[i-j+1]→s[i])的计算可以简化成在把j从1→k遍历的同时不断更新最大值(具体看代码)。只需要把dp数组从i=1到i=n遍历一遍,最后输出dp[n]即可,时间复杂度为O(NK)。

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 const int INF=0x3f3f3f3f;
12 using namespace std;
13 
14 int dp[10001];
15 int a[10001];
16 
17 int main()
18 {
19     int n,k;
20     scanf("%d%d",&n,&k);
21     for(int i=1;i<=n;i++)
22         scanf("%d",&a[i]);
23     dp[1]=a[1];
24     int maxn;
25     for(int i=2;i<=n;i++)
26     {
27         maxn=0;
28         for(int j=1;j<=k&&i-j>=0;j++)
29     {
30         if(maxn<a[i-j+1]) maxn=a[i-j+1];
31         //这里顺便记录并更新最大值
32         dp[i]=max(dp[i],dp[i-j]+maxn*j);
33     }
34     }
35     printf("%d\n",dp[n]);
36     return 0;
37 }

猜你喜欢

转载自www.cnblogs.com/VBEL/p/10394001.html
今日推荐