【NOIP2016提高A组模拟8.17】Value

本文介绍了一个特定类型的背包问题,通过动态规划求解最优解。针对每个物品有两个值a和b的特点,文章给出了详细的DP方程推导过程,并分享了代码实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

这里写图片描述
Input
这里写图片描述
Sample Input
5
8 2
10 7
5 1
11 8
13 3
Output
这里写图片描述
Sample Output
27
Data Constraint
这里写图片描述

题目大意

现在有N个数,每个数都有两个值,a和b,每次我们可以选择一个物品(每个物品只可以不选或者选一次)我们可以获得a的贡献,但是我们后面拿的每样物品贡献都要减去b(比如在拿完物品i后又拿了j样物品,那么最终的答案减少bij)。现在我们想知道怎么样拿可以获得最多的贡献

比赛时の想法

这种类型的题最近做了好几次了,所以大多数人都推出了正解,但是有一部分人(比如我)找到了“反例”,于是就没有打正解QAQ

正解

自己出几组数据,然后van(玩)一下,发现如果我们已经确定要选哪些数,那么取的顺序肯定是按wi从小到大牌序,所以我们先以wi为关键字排一次序(从大到小)那么最优解一定是倒序选择一些物品,于是我们可以设f[i,j]表示现在DP做到第i个位置,选了最后的j个数,显然,f[i,j]=max(f[i1,j],f[i1,j1]+v[i]w[i](j1))倒着做的原因是这样方便计算每个wi对于答案的贡献,因为它只对在自己后面选择的物品有影响

贴代码

写出来就十分简单了

var
    f:array[0..5005,0..5005]of longint;
    t1,t2:array[0..5005]of longint;
    i,j,k,l,n:longint;
procedure qsort(l,r:longint);
var
    i,j,mid:longint;
begin
    i:=l;
    j:=r;
    mid:=t2[(i+j) div 2];
    repeat
        while t2[i]>mid do inc(i);
        while t2[j]<mid do dec(j);
        if i<=j then
        begin
            t1[0]:=t1[i]; t1[i]:=t1[j]; t1[j]:=t1[0];
            t2[0]:=t2[i]; t2[i]:=t2[j]; t2[j]:=t2[0];
            inc(i); dec(j);
        end;
    until i>j;
    if i<r then qsort(i,r);
    if l<j then qsort(l,j);
end;
function max(x,y:longint):longint;
begin
    if x>y then exit(x) else exit(y);
end;
begin
   readln(n);
   for i:=1 to n do readln(t1[i],t2[i]);
   qsort(1,n);
   for i:=1 to n do
       for j:=1 to i do
           f[i,j]:=max(f[i-1,j],f[i-1,j-1]+t1[i]-t2[i]*(j-1));
   f[0,0]:=0;
   for i:=1 to n do f[0,0]:=max(f[0,0],f[n,i]);
   writeln(f[0,0]);
end.
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值