首先直接做多重背包肯定会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.