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

题目链接: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.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值