题目
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样物品,那么最终的答案减少bi∗j)。现在我们想知道怎么样拿可以获得最多的贡献
比赛时の想法
这种类型的题最近做了好几次了,所以大多数人都推出了正解,但是有一部分人(比如我)找到了“反例”,于是就没有打正解QAQ
正解
自己出几组数据,然后van(玩)一下,发现如果我们已经确定要选哪些数,那么取的顺序肯定是按wi从小到大牌序,所以我们先以wi为关键字排一次序(从大到小)那么最优解一定是倒序选择一些物品,于是我们可以设f[i,j]表示现在DP做到第i个位置,选了最后的j个数,显然,f[i,j]=max(f[i−1,j],f[i−1,j−1]+v[i]−w[i]∗(j−1))倒着做的原因是这样方便计算每个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.