「NOIP2017模拟赛09.07」不解释连招

来源:互联网 发布:中国网络战部队 编辑:程序博客网 时间:2024/05/02 18:43

题目链接:http://hhhoj.ngrok.cc/contest/4/problem/11
贪心思想,ciwi的值越大,说明这个技能越强,能用则用
那么问题来了,也许会出现这样的情况,你还漏下一些空不好塞,但拿掉些个大的,用一些小的可以刚好填满,并满足情况最优,于是乎就出现了一些纠结
如果看完题目,不难发现,突破口在于1wi3也就是说,如果按照先前的方法放,出现纠结时,最多出现2个空,因为尽可能少换是王道,所以交换的情况是有限的,背包出前后取1,2,3的情况再判一下就好了
贴代码

const maxn=100005; var a,b:array[0..maxn]of int64;     c,d:array[0..5]of int64;     n:longint;     m,dt1,dt2,dt3,ans:int64; procedure swap(var x,y:int64);  var t:int64;   begin    t:=x;x:=y;y:=t;   end; procedure qsort(L,R:longint);  var i,j,mid:longint;mida,midb:int64;   begin    i:=L;j:=R;mid:=random(R-L+1)+L;    mida:=a[mid];midb:=b[mid];    repeat     while mida*b[i]>a[i]*midb do inc(i);     while mida*b[j]<a[j]*midb do dec(j);      if i<=j then begin                    swap(a[i],a[j]);swap(b[i],b[j]);                    inc(i);dec(j);                   end;    until i>j;    if i<R then qsort(i,R);    if L<j then qsort(L,j);   end; procedure init;  var i,j:longint;   begin //   assign(input,'2.in');reset(input); //   assign(output,'2.out');rewrite(output);    read(n,m);    for i:=1 to n do read(a[i],b[i]);   end; procedure main;  var i,j,bo:longint;      INF:int64;   begin    qsort(1,n);    bo:=0; ans:=0;    for i:=1 to n do     begin      if m=0 then break;      if a[i]>m then begin bo:=i;break; end;      ans:=ans+b[i];      dec(m,a[i]);     end;    fillchar(d,sizeof(d),255);    fillchar(c,sizeof(c),63);    c[0]:=0;INF:=c[1];d[0]:=0;    for i:=1 to bo-1 do     for j:=3 downto a[i] do      if c[j-a[i]]<>INF then       if c[j-a[i]]+b[i]<c[j] then c[j]:=c[j-a[i]]+b[i];    for i:=bo to n do     for j:=3 downto a[i] do      if d[j-a[i]]<>-1 then       if d[j-a[i]]+b[i]>d[j] then d[j]:=d[j-a[i]]+b[i];    dt1:=-1;dt2:=-1;dt3:=-1;    if d[1]<>-1 then dt1:=d[1];    if d[2]<>-1 then dt2:=d[2];    if d[3]<>-1 then dt3:=d[3];    if c[1]<>INF then begin                       if d[2]<>-1 then if d[2]-c[1]>dt1 then dt1:=d[2]-c[1];                       if d[3]<>-1 then if d[3]-c[1]>dt2 then dt2:=d[3]-c[1];                      end;    if c[2]<>INF then     if d[3]<>-1 then if d[3]-c[2]>dt1 then dt1:=d[3]-c[2];    if dt1>dt2 then dt2:=dt1;    if dt2>dt3 then dt3:=dt2;    if m=3 then if dt3<>-1 then ans:=ans+dt3;    if m=2 then if dt2<>-1 then ans:=ans+dt2;    if m=1 then if dt1<>-1 then ans:=ans+dt1;   end; procedure print;  begin   writeln(ans); //  close(input);close(output);  end; begin  init;  main;  print; end.

【写的有漏洞的,欢迎路过大神吐槽】
2017/09/08 22:51:13
Ending.

原创粉丝点击