原题
题目大意
有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 }