jzoj P1286 太空电梯

题目大意:
奶牛们想用K中石块制造一个太空电梯去太空旅行,每种石块有自己的高度h_i和数量c_i,为了避免宇宙射线的干扰,每种石块不能超过最高可以达到的高度a_i。求奶牛能用石块堆积的最高的太空电梯

1<=K<=400
1<=c_i<=10
1<=h_i<=100
1<=a_i<=40000

题解:
排序+枚举:
这题很明显先要用a[i]排序,因为这样使得a[i]变成升序,结果就能前面完全影响后面,而如果一大一小一大,枚举就就出错。
设f[i,j]表示前i个块石头中j这个数是否出现过,1为出现过,0即为没有
//是排完序后的石头顺序

然后推
i从1 to k
j从a[i] downto 0 //顺着的话要开二维,不然逆推就可以优化掉一个维度
k从1 to c[i] //先判断j是否出现过,再进行,即f[j]=1
然后如果j+k*h[i]>a[i] //不能超过其限度
就f[j+k*h[i]]=1
最后在出现过的数中找最大值。
时间复杂度:O(Σc[i]*a[i]) //i从1到K

var
   a:Array [0..401,1..3] of longint;
   f:Array [0..40001] of longint;
   i,j,k,n:longint;

procedure qsort(l,r:longint);
var
   i,j,mid:longint;
begin
   if l>=r then exit;
   mid:=a[(l+r) div 2,2];
   i:=l; j:=r;
   repeat
        while a[i,2]do inc(i);
        while a[j,2]>mid do dec(j);
        if i<=j then
        begin
             a[0]:=a[i];
             a[i]:=a[j];
             a[j]:=a[0];
             inc(i);
             dec(j);
        end;
   until i>j;
   qsort(i,r);
   qsort(l,j);
end;

begin
    readln(n);
    for i:=1 to n do
      readln(a[i,1],a[i,2],a[i,3]);
    qsort(1,n);
    f[0]:=1;
    for i:=1 to n do
    begin
         for j:=a[i,2] downto 0 do
           if f[j]=1 then
              for k:=1 to a[i,3] do
              begin
                   if j+k*a[i,1]>a[i,2] then break;
                   f[j+k*a[i,1]]:=1;
              end;
    end;

    for i:=a[n,2] downto 0 do
      if f[i]=1 then
      begin
          writeln(i);
          halt;
      end;
end.

你可能感兴趣的:(暴力/枚举/模拟,排序&拓扑,pascal)