数字游戏

来源:互联网 发布:英译汉软件下载 编辑:程序博客网 时间:2024/04/30 20:46

题意

小W发明了一个游戏,他在黑板上写出了一行数字a1,a2,a3,……,an,然后给你M个回合的机会,每会回你可以从中选择一个数字擦去它,接着剩下来的每个数字ai都要递减一个值bi。如此重复m个回合,所有你擦去的数字之和就是你所得的分数。小W和他的好朋友小Y玩了这个游戏,可是他发现,对于每个给出的a和b序列,小Y的得分总比他高,所以他就很不服气。于是他想让你帮他算算,对于每个a和b序列,可以得到的最大得分是多少。


分析

我们知道,擦走的数字是有顺序的。如果可以规定一个序,删除的顺序必需和这个序相对应,就可以应用动态规划了。

设F[i,j]表示从前i个删除j个数的最大分值。

f[i,j]:=max{f[i-1,f[i-1,j-1]+a[i]-b[i]*(i-1)}




var
a,b:array[0..2001]of longint;
n,m,i,j:longint;
f:array[0..2001,0..2001]of longint;
procedure kp(l,r:longint);
var
i,j,mid:longint;
begin
    if l>r then exit;
    i:=l;j:=r;mid:=b[(l+r) div 2];
    repeat
         while b[i]>mid do inc(i);
         while b[j]<mid do dec(j);
         if i<=j then
         begin
             b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
             a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
             inc(i);dec(j);
         end;
    until i>j;
    kp(l,j);
    kp(i,r);
end;


begin
    readln(n);readln(m);
    for i:=1 to n do
    read(a[i]);
    readln;
    for i:=1 to n do
    read(b[i]);
    kp(1,n);
    fillchar(f,sizeof(f),200);
    for i:=1 to n do
    begin
        f[i-1,0]:=0;
        for j:=1 to m do
        if f[i-1,j]<f[i-1,j-1]+a[i]-b[i]*(j-1) then f[i,j]:=f[i-1,j-1]+a[i]-b[i]*(j-1) else f[i,j]:=f[i-1,j];
    end;
    write(f[n,m]);
end.

0 0
原创粉丝点击