• 解题报告 poj 3093


    1.        题目

    poj 3093

    2.        题目实质

    给定一个01背包和n个物品,求有多少种选择方法使得背包再也放不下余下的任意物品。

    3.        算法

    预处理:按照物品体积排序。

    首先,枚举第一个有可能装不下的物品(这里从大到小枚举,可以省去求和的时间),这样一来,他之前的物品一定都能装下,从背包的总体积中减去。

    然后再对可能装不下的物品(比枚举的这个物品大的)做一下改版的 01 背包,也就是 01 背包求方案数:那么 i 为最小进不了物品时,对应的方案数就是:以比 i 大的物品做一个容积为(背包容积 - sum(<i) )的 01 背包,使得剩余的容积不足 Vi 的方案数。

    4.        注意事项

    搜索的全部超时去吧......这是个动规。

    5.        代码

    改版 01 背包 (SueMiller)

    program ACRush;

     

    var ca,cas:longint;

        n,m:longint;

        a,f:array[0..1001]of longint;

        i,j,k:longint;

        ans,sum:longint;

     

    procedure quicksort(l,r:longint);

    var x,y,i,j:longint;

    begin

     i:=l; j:=r; x:=a[(l+r)>>1];

     repeat

      while a[i]<x do inc(i);

      while x<a[j] do dec(j);

      if i<=j then

       begin

       y:=a[i]; a[i]:=a[j]; a[j]:=y;

       inc(i); dec(j);

       end;

     until i>j;

     if l<j then quicksort(l,j);

     if i<r then quicksort(i,r);

    end;

     

    function max(a,b:longint):longint;

    begin

      if a>b then exit(a) else exit(b);

    end;

     

    begin

      readln(cas);

      for ca:=1 to cas do

        begin

          fillchar(a,sizeof(a),0);

          readln(n,m);

          sum:=0;

          for i:=1 to n do

            begin

              read(a[i]);

              sum:=sum+a[i];

            end;

          readln;

     

          if sum<=m then

            begin

              writeln(ca,' ',1);

              continue;

            end;

          if a[1]>m then

            begin

              writeln(ca,' ',0);

              continue;

            end;

     

          quicksort(1,n);

          ans:=0;

          fillchar(f,sizeof(f),0);

          f[0]:=1;

    //---------------------这是核心部分----------------------

          for i:=n downto 1 do

            begin

              sum:=sum-a[i];

     

              for j:=max(m-sum-a[i]+1,0) to m-sum do

                ans:=ans+f[j];

     

      for j:=m downto a[i] do

                f[j]:=f[j-a[i]]+f[j];

     

            end;

    //-------------------------------------------------------------

     

          writeln(ca,' ',ans);

        end;

     

    end.

     

    (* 其实我觉得背包类动规是个好神奇的东西,像这个 01 背包,我一直感觉着答案递推不出来,只能用递归做,但事实上它确实是出来了。所以呢,这方程,我还是生背的。*)

    //本博客有置顶 dd_engi 的背包九讲。

  • 相关阅读:
    读《疯狂Ajax讲义》重点
    Qt Library 链接库
    html验证码
    java开发webservice
    QT TCP/IP
    Android 开发技术流程
    jquery使用
    多台服务之间共享Session
    JS 混淆加密
    html中的表格 bootstrap-table
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2215440.html
Copyright © 2020-2023  润新知