Rabbit的工作(2)
题目
链接:https://ac.nowcoder.com/acm/problem/21186
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
题目描述
Rabbit通过了上次boss的考核,现在她又遇到了一个问题。
Rabbit接到了K个任务,每个任务她可以自由选择用i天去完成(1≤ i≤ N)。刁钻的boss想让Rabbit恰好用W天完成所有任务。
已知Rabbit用i天完成一个任务能让boss获得的满意度为vi(因为完成任务的质量不同),她想知道在满足boss要求的情况下能让boss获得的总满意度最大是多少。
输入描述:
第一行三个整数N,K,W。
第二行N个整数vi,vi表示用i天完成一个任务能让boss获得的满意度。
输出描述:
输出Rabbit在满足boss要求的情况下能让boss获得的总满意度最大是多少。
示例1
输入
复制
3 3 5
6 2 4
输出
复制
16
说明
Rabbit可以选择分别用1天,1天,3天完成这三个任务,最大满意度为6+6+4=16
备注:
2≤ N,K≤ 2000,K≤ W≤ min(4000,2*K)
0<vi≤ 10000
解题思路
为了保证在w天我们刚好完成k个任务,我们先保存k个一天的满意度,之后我们只需要通过差分,算出其余天数与第一天的差值,就能转化为完全背包,比如样例,先保存3个第一天的满意度18,之后得到第二天的值是-4,第三天为-2,还剩下2(w-k)天,完全背包求最终解
w-=k;
dp[0]=k*v[0];
for(int i=1;i<n;i++){
for(int j=i;j<=w;j++){
dp[j]=max(dp[j],dp[j-i]+v[i]);
}
}
此时可能有同学会有小疑问,你怎么能保证后面的dp也是k天,比如输入为 3 3 7 6 7 2,答案应该为16(7+7+2),但是代码输出却是22,为什么错了呢,这是因为我们虽然保证了有k个一天,但是取无法限制第二天及以后的天数,刚刚的例子第二天出现了w-k次,也就是4次,差分之后为1(7-6),加上3个第一天的满意度和18,出来了22这个答案,显然第二天的数量居然比第一天还多,但是代码依然AC了,是因为题目最后给出的w的范围,k<=w<=2*k,这样我们取完k个一天,剩下的w-k天已经无法超过k的范围,第二天及其之后的天数也就被限制在了k天以内,我觉得出题者之所以这样限制范围,本意就是让用这种方法解题吧,最后附上AC代码
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 2005
using namespace std;
int v[MAX];
int dp[2*MAX];
int main(){
int n,k,w;
scanf("%d%d%d",&n,&k,&w);
for(int i=1;i<=w;i++){
dp[i]=-2e9;
}
scanf("%d",&v[0]);
for(int i=1;i<n;i++){
scanf("%d",&v[i]);
v[i]-=v[0];
}
w-=k;
dp[0]=k*v[0];
for(int i=1;i<n;i++){
for(int j=i;j<=w;j++){
dp[j]=max(dp[j],dp[j-i]+v[i]);
}
}
printf("%d",dp[w]);
}
蒟蒻一枚,如果有错,欢迎指正