Rabbit的工作(2)

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]);
}

蒟蒻一枚,如果有错,欢迎指正

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值