zoukankan      html  css  js  c++  java
  • bzoj1042

    首先直接做多重背包肯定会TLE的,

    观察这个背包问题有什么特殊性呢

    物品种类和重量,价值是一定的,不同的是背包的容量和物品的数量

    由于当物品数量没有限制的时候,方案数是可以预处理出来的

    所以我们考虑用ans=物品数量没有限制时的方案数-物品超出限制的方案数来解决

    第一部分是可以用完全背包来解决的

    第二问不难想到用容斥原理来解决

    设f[m]为容量为m时的方案数

    假如当i号物品超出数量s[i]限制(不知道其他物品有没有超),方案数f[m-w[i]*(s[i]+1)](严格超出限制

    以此类推,可得出多个物品超出限制的方案数

    根据容斥原理,计算一下即可

     1 var f:array[0..100010] of int64;
     2     w:array[1..4] of longint;
     3     c:array[0..1010,0..4] of longint;
     4     t:array[0..1010] of longint;
     5     i,n,j,k,p,y,m,s:longint;
     6     ans:int64;
     7 
     8 begin
     9   for i:=1 to 4 do
    10     read(w[i]);
    11   readln(n);
    12   for i:=1 to n do
    13   begin
    14     for j:=1 to 4 do
    15       read(c[i,j]);
    16     readln(t[i]);
    17     if t[i]>m then m:=t[i];
    18   end;
    19   f[0]:=1;
    20   for i:=1 to 4 do
    21     for j:=w[i] to 100000 do
    22       f[j]:=f[j]+f[j-w[i]];
    23 
    24   for i:=1 to n do
    25   begin
    26     ans:=0;
    27     for j:=0 to 15 do   //用二进制表示物品是否超出限制
    28     begin
    29       s:=t[i];
    30       y:=0;
    31       for k:=1 to 4 do
    32       begin
    33         p:=1 shl (k-1);
    34         if j and p<>0 then
    35         begin
    36           s:=s-w[k]*(c[i,k]+1);
    37           if s<0 then break;
    38           inc(y);
    39         end;
    40       end;
    41       if s<0 then continue;   //注意可能不存在某几个物品都超出限制的情况
    42       if y mod 2=1 then ans:=ans-f[s] else ans:=ans+f[s];
    43     end;
    44     writeln(ans);
    45   end;
    46 end.
    View Code
  • 相关阅读:
    Linux/shell: remove adjacent similar patterns
    Calculate difference between consecutive data points in a column from a file
    awk
    自定义Cordova插件(基础篇)
    npm init 命令生成package.json文件
    自定义Cordova插件详解
    Android 回退键监听
    Cordova结合Vue学习Camera
    解决悬浮的<header>、<footer>遮挡内容的处理技巧
    npm 是干什么的
  • 原文地址:https://www.cnblogs.com/phile/p/4473179.html
Copyright © 2011-2022 走看看