• BZOJ1190:[HNOI2007]梦幻岛宝石


    Description

    给你N颗宝石,每颗宝石都有重量和价值。要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值。数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符合a*2^b(a<=10;b<=30)

    Input

    输入文件中包含多组数据。每组数据的格式如下:第一行是两个正整数n和W,1≤n≤100,1≤W≤2^30,分别表示宝石的数目和最多能带走的宝石重量。接下来的n行,每行有两个正整数weighti和valuei,1≤weighti≤2^30, 0≤valuei≤2^30,分别表示第i颗宝石的重量和价值,且保证weighti能写成a*2^b(1≤a≤10,0≤b≤30)的形式。同一行的两个正整数之间用空格隔开。最后一组数据的后面有两个-1,表示文件的结束。这两个-1并不代表一组数据,你不需对这组数据输出结果。并且输入文件中数据的组数不超过20。

    Output

    对于输入的每组数据,输出一个整数C,表示小P最多能带走的宝石的总价值。每个结果整数C单独占一行,且保证C不会超过2^30。

    Sample Input

    4 10
    8 9
    5 8
    4 6
    2 5
    4 13
    8 9
    5 8
    4 6
    2 5
    16 75594681
    393216 5533
    2 77
    32768 467
    29360128 407840
    112 68
    24576 372
    768 60
    33554432 466099
    16384 318
    33554432 466090
    2048 111
    24576 350
    9216 216
    12582912 174768
    16384 295
    1024 76
    -1 -1

    Sample Output

    14
    19
    1050650
     

    题解:

    显然这是一个01背包,但是体积容积都特别大。

    事实上,每颗宝石体积在2进制情况下的有效位数都特别有限,可以对体积按位dp。

    F[i,j]表示当前DP到第i位,使用j*2^(i-1)体积可以得到的最大价值。对于i的阶段,只要用b=i-1的宝石去DP,然后进位转移到下一阶段。

    因为a<=10,n<=100,j最多为1000。

    注意考虑上界,需额外开一个数组表示所考虑有效位数之后的数都在W对应范围内的情况。

    代码:

     1 uses math;
     2 var
     3   i,j,k,l,n,m,ii,ww:longint;
     4   tot,w:int64;
     5   a:array[0..1,0..40,0..1001]of int64;
     6   s:array[0..40]of longint;
     7   b:array[0..101,0..2]of int64;
     8   t:array[0..2]of int64;
     9 begin
    10   while true do
    11   begin
    12     readln(n,w); tot:=0;
    13     //w:=50000;
    14     if n=-1 then break;
    15     for i:=1 to n do
    16     begin
    17       readln(b[i,1],b[i,0]);
    18       b[i,2]:=1;
    19       while b[i,1] mod 2=0 do begin b[i,1]:=b[i,1] div 2; inc(b[i,2]); end;
    20     end;
    21     for i:=1 to n-1 do
    22     for j:=i+1 to n do
    23     if b[i,2]>b[j,2] then begin t:=b[i]; b[i]:=b[j]; b[j]:=t; end;
    24     fillchar(a,sizeof(a),0);
    25     if n=-1 then break;
    26     l:=0;
    27     while w>0 do
    28     begin
    29       inc(l); s[l]:=w mod 2;
    30       w:=w div 2;
    31     end;
    32     ii:=1;
    33     for i:=1 to l do
    34     begin
    35       for j:=0 to 1000 do
    36       if(s[i-1]=1)or(j mod 2=0)then
    37       begin
    38         a[0,i,j div 2]:=max(a[0,i,j div 2],a[0,i-1,j]);
    39         a[0,i,j div 2]:=max(a[1,i,j div 2],a[0,i-1,j]);
    40       end;
    41       for j:=0 to 1000 do
    42       begin
    43         a[1,i,(j div 2)+1]:=max(a[1,i,(j div 2)+1],a[1,i-1,j]);
    44         if j mod 2=0 then
    45         a[1,i,j div 2]:=max(a[1,i,j div 2],a[1,i-1,j]);
    46       end;
    47       while(ii<=n)and(b[ii,2]<=i)do
    48       begin
    49         for j:=1000-b[ii,1] downto 0 do
    50         begin
    51           a[0,i,j+b[ii,1]]:=max(a[0,i,j+b[ii,1]],a[0,i,j]+b[ii,0]);
    52           a[1,i,j+b[ii,1]]:=max(a[1,i,j+b[ii,1]],a[1,i,j]+b[ii,0]);
    53         end;
    54         inc(ii);
    55       end;
    56       for j:=1 to 1000 do begin a[0,i,j]:=max(a[0,i,j],a[0,i,j-1]);
    57       a[1,i,j]:=max(a[1,i,j-1],a[1,i,j]); end;
    58     end;
    59     writeln(max(a[1,l,1],a[0,l,1]));
    60   end;
    61 end.
    View Code
  • 相关阅读:
    栈的经典运用-求值数学表达式
    java中Stack的源码解析
    java-背包的实现
    数据库的事务的特性及隔离级别
    EnumMap的用法和源码解析
    java final关键字的解析
    java中的static关键字解析
    XPath如何定位dom节点
    java 枚举(enum) 详细用法
    jdk动态代理
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6254898.html
Copyright © 2020-2023  润新知