Description
给定 n n 个物品,每个物品价值为 vi vi ,代价为 wi wi 。
可以以任意的顺序选择任意数量的物品,但在选择编号为 i i 的物品后,剩下物品的价值都会减少 wi wi 。
要求最大化选择商品的价值之和。
Input
第一行包含两个整数nn。
之后 n n 行每行包含两个整数 vi,wi。 vi,wi。
Output
共一行,表示最大化选择商品的价值之和。
Data Constraint
n≤5000,vi,wi≤105。n≤5000,vi,wi≤105。
Sample Input
5
8 2
10 7
5 1
11 8
13 3
Sample Output
27
Solution
显然,先将代价升序排序,贪心地先选代价较小的物品,从而对后面选的造成影响最小。
设 fi,j fi,j 为选前 i i 个物品,在其后还要选 j j 个物品的最优解。
DP式:
fi,j=max( fi−1,j , fi−1,j+1+vi−wi∗j)fi,j=max( fi−1,j , fi−1,j+1+vi−wi∗j)
那么答案就是 fn,0 fn,0。
code
const maxn=5005;
var i,j,n,ans:longint;
w,v:array[1..maxn] of int64;
f:array[0..maxn,0..maxn] of int64;
function max(x,y:int64):int64;
begin
if x>y then exit(x);exit(y);
end;
procedure swap(var x,y:int64);
var t:int64;
begin
t:=x;
x:=y;
y:=t;
end;
procedure qsort(x,y:longint);
var i,j:longint;
k:int64;
begin
i:=x;
j:=y;
k:=w[(i+j) shr 1];
repeat
while w[i]<k do inc(i);
while w[j]>k do dec(j);
if i<=j then begin
swap(w[i],w[j]);
swap(v[i],v[j]);
inc(i);dec(j);
end;
until i>j;
if i<y then qsort(i,y);
if j>x then qsort(x,j);
end;
begin
readln(n);
for i:=1 to n do readln(v[i],w[i]);
qsort(1,n);
for i:=1 to n do
for j:=0 to n-i do
f[i,j]:=max(f[i-1,j],f[i-1,j+1]+v[i]-w[i]*j);
writeln(f[n,0]);
end.