2017.2.12【初中部 GDKOI】模拟赛B组 T2:宿敌

**【NOIP2014模拟7.10】宿敌(enemy) **
2014 年到了,T国和S 国在紧张交战中,现在到了最后一战。T国是一个实力很强的国家,在T国中,有一批为作战献身的机器人,对于任意一个机器人,有一个属性值pi,这个值越大,表示实力越强。T国将准备一支由n 个机器人组成的队伍,按照编号依次排开。

队伍准备就绪后,T 国的国王W 君发现这支队伍实在是不堪入目,他发现这些机器人的实力值参差不齐,W 君希望让这支队伍能在战场中发挥出最佳实力。

按照经验,当且仅当这n 个机器人的实力值为单调不增或单调不减时,我们称这样的n 个机器人组成的队伍为一个合格的队伍。于是W 君拿出编写机器人时的工具,准备对每个机器人的实力值进行修改。

其中,增加第i 个机器人的实力值,需要的费用为m1,减小第i 个机器人的实力值,需要的费用为m2,若不对第i 个机器人的实力值进行修改,则费用为0。无论实力值增加多少,费用均为m1,无论实力值减小多少,费用均为m2。

现在,给出n 个机器人的实力值,由于战争进行已久,T国的经费有限,请求出这个最小的修改代价,使得修改后的队伍成为一个合格的队伍。

注意:由于在制造机器人时的能力有限,对于n 个机器人,不同的实力值不会超过1,000个。

Input

输入文件共包含两行。

第一行共包括3 个正整数,分别为n,m1,m2。

第二行为n 个整数,第i 个整数表示第i 个机器人的实力值为pi。

Output

共一行,只有一个整数,为使得原队伍成为合格的队伍需要的最小修改代价。

Sample Input

5 1 1

1 3 2 2 1

Sample Output

1

【样例说明】

若将这个队伍改为单调不减的队伍,则至少需要对2 个机器人的实力值进行

修改,费用为1×1+1×1=2,其中一种可行的方案是将第2 个机器人的实力值

减小为2,将第5 个机器人的实力增加为3。而若将这个队伍改为单调不增的队

伍,则只需将第1 个机器人的实力由1 增加为3 即可,费用为1×1=1。

Data Constraint
这里写图片描述
题解:
对于%50的数据:
我们发现,m1=m2=1所以我们就直接考虑用一个最长不下降子序列和一个最长不上升子序列,然后用n减去这些东西,比较即可。
O(n^2)
对于75%我们又发现,pi只有2种取值,那么只需枚举i的位置即可O(n)。
对于100%我们用一个离散化来把大数据给变得很小,离散到1~1000的数。然后用动态规划。f[i,j]表示将前 i 个机器人改为单调不减,第 i 个机器人的实力值变为 j 所需的最小费用。那么DP方程很好推:f[i,j]=min(f[i-1,k])+change(a[i],j)。这时,会发现时间炸了O(nT^2).
注意到对于当前的决策位置,k 的可取值越来越多,因此可以再同时维护 min(f[i-1,k]),这样转移代价变成 O(1),时间复杂度变为 O(nT)
标程:

type
        new = array [0..50000] of longint;
var
        i,j,k,l,n,m,m1,m2,t,ans:longint;
        f,g:array[0..50000,1..1000] of longint;
        a,d:new;
procedure discretize (var a : new); //离散化主程序
var
        i,j,k:longint;
        b, c : new;
procedure qsort (l, r : longint);
var
        x, y : longint;
        i, j : longint;
begin
        i := l;
        j := r;
        x := a [(l + r) div 2];
        repeat
                while a [i] < x do inc (i);
                while x < a [j] do dec (j);
                if not (i > j) then
                begin
                        y := a [i];
                        a [i] := a [j];
                        a [j] := y;
                        y := b [i];
                        b [i] := b [j];
                        b [j] := y;
                        inc (i);
                        dec (j);
                end;
        until i > j;
        if l < j then qsort (l, j);
        if i < r then qsort (i, r);
end;
begin
        fillchar (b, sizeof (b), 0);
        fillchar (c, sizeof (c), 0);
        for i := 0 to n do b [i] := i;
        qsort (0, n);
        j:=0;
        c [b [0]] := 0;
        for i := 1 to n do
        if (a [i] = a [i - 1]) then
        begin
                c [b [i]] := c [b [i - 1]];
        end
        else
        begin
                inc(j);
                c [b [i]] := j;
        end;
        fillchar (a, sizeof (a), 0);
        for i := 0 to n do
        begin
                if c[i]>t then t:=c[i];
                a [i] := c [i];
        end;
end;
function min(x,y:longint):longint;
begin
        if x>y then exit(y) else exit(x);
end;
function max(x,y:longint):longint;
begin
        if x<y then exit(y) else exit(x);
end;
function chang(x,y:longint):longint;
begin
        if x<y then exit(m1)
        else if x>y then exit(m2)
        else exit(0);
end;
begin
        assign(input,'enemy.in');reset(input);
        assign(output,'enemy.out');rewrite(output);
        readln(n,m1,m2);
        for i:=1 to n do
        begin
                read(a[i]);
        end;
        discretize(a);
        for i:=1 to n do
        begin
                k:=maxlongint;
                for j:=1 to t do
                begin
                        k:=min(k,f[i-1,j]);
                        f[i,j]:=k+chang(a[i],j);
                end;
        end;
        ans:=maxlongint;
        for i:=1 to t do
        ans:=min(f[n,i],ans);
        j:=n;
        d:=a;
        for i:=1 to n div 2 do
        begin
                d[i]:=a[j];
                d[j]:=a[i];
                dec(j);
        end;
        for i:=1 to n do
        begin
                k:=maxlongint;
                for j:=1 to t do
                begin
                        k:=min(k,g[i-1,j]);
                        g[i,j]:=k+chang(d[i],j);
                end;
        end;
        for i:=1 to t do
        ans:=min(g[n,i],ans);
        writeln(ans);
        close(input);close(output); 
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值