poj 3093 Margaritas on the River…

Description

One of the more popular activities in San Antonio is to enjoy margaritas in the park along the river know as the River Walk. Margaritas may be purchased at many establishments along the River Walk from fancy hotels to Joe’s Taco and Margarita stand. (The problem is not to find out how Joe got a liquor license. That involves Texas politics and thus is much too difficult for an ACM contest problem.) The prices of the margaritas vary depending on the amount and quality of the ingredients and the ambience of the establishment. You have allocated a certain amount of money to sampling different margaritas.

Given the price of a single margarita (including applicable taxes and gratuities) at each of the various establishments and the amount allocated to sampling the margaritas, find out how many different maximal combinations, choosing at most one margarita from each establishment, you can purchase. A valid combination must have a total price no more than the allocated amount and the unused amount (allocated amount – total price) must be less than the price of any establishment that was not selected. (Otherwise you could add that establishment to the combination.)

For example, suppose you have $25 to spend and the prices (whole dollar amounts) are:

VendorABCDHJ
Price8987165

Then possible combinations (with their prices) are:

ABC(25), ABD(24), ABJ(22), ACD(23), ACJ(21), ADJ( 20), AH(24), BCD(24), BCJ(22), BDJ(21), BH(25), CDJ(20), CH(24), DH(23) and HJ(21).

Thus the total number of combinations is 15.

Input

The input begins with a line containing an integer value specifying the number of datasets that follow, N (1 ≤ N ≤ 1000). Each dataset starts with a line containing two integer values V and D representing the number of vendors (1 ≤ V ≤ 30) and the dollar amount to spend (1 ≤ D ≤ 1000) respectively. The two values will be separated by one or more spaces. The remainder of each dataset consists of one or more lines, each containing one or more integer values representing the cost of a margarita for each vendor. There will be a total of V cost values specified. The cost of a margarita is always at least one (1). Input values will be chosen so the result will fit in a 32 bit unsigned integer.

Output

For each problem instance, the output will be a single line containing the dataset number, followed by a single space and then the number of combinations for that problem instance.

Sample Input

2
6 25
8 9 8 7 16 5
30 250
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30

Sample Output

1 15
2 16509438

Hint

Note: Some solution methods for this problem may be exponential in the number of vendors. For these methods, the time limit may be exceeded on problem instances with a large number of vendors such as the second example below.

Source

 
题目大意:给定一个背包和n个物品,求有多少种选择方法使得背包再也放不下余下的任意物品。
 
对于这题,可以先考虑放i个物品,所用体积为j的方法有多少种。这就可以用类似0-1背包的方法实现:
f[i,j]=f[i-1,j]+f[i-1,j-v[i]]  //考虑放或者不放两种情况。
再来考虑放不下其他任一物品的条件。
我们可以通过枚举剩下物品中的体积最小的物品,把体积比它小的物品都放入背包,体积比它大的物品做一次背包,把情况数记录在f数组中,然后对满足放不下物品i的f数组区间进行求和,加到答案中去。
很明显,这题要先排序,然后依次枚举剩余物品中体积最小的物品,做一次背包。
如果从小到大枚举,每一次要做背包的物品都减少一个物品所以要重新做一次,复杂度为O(n^2*C)。
如果从大到小枚举,则每一次都是新加入一个物品,只要for一遍即可,复杂度为O(n*C)。
 
AC CODE

program pku_3093;


var f:array[0..1000000] of longint;


    v,sum:array[0..1000] of longint;


    n,all,i,c:longint;


//============================================================================


procedure qsort(s,t:longint);


var i,j,k,tt:longint;


begin


  k:=v[(s+t) shr 1]; i:=s; j:=t;


  repeat


    while v[j]>k do dec(j);


    while v[i]<k do inc(i);


    if i<=j then


    begin


      tt:=v[i]; v[i]:=v[j]; v[j]:=tt;


      inc(i); dec(j);


    end;


  until i>j;


  if j>s then qsort(s,j);


  if i<t then qsort(i,t);


end;


//============================================================================


procedure init;


var i:longint;


begin


  readln(n,c);


  for i:=1 to n do read(v[i]);


  qsort(1,n);


  for i:=0 to c do f[i]:=0;


  for i:=1 to n do sum[i]:=sum[i-1]+v[i];


end;


//============================================================================


procedure work;


var ans,i,j:longint;


begin


  init; f[0]:=1; ans:=0;


  if c<v[1] then


  begin writeln('0'); exit; end;


  if c>=sum[n] then


  begin writeln('1'); exit; end;    //discuss里面的两个特判。


  for i:=n downto 1 do


  begin


    //if sum[i-1]>c then continue;    //如果多了这句,就不能把某些物品放入背包,会错。。


    if c-sum[i]+1>0 then


    for j:=c-sum[i-1] downto c-sum[i]+1 do inc(ans,f[j]) else


    for j:=c-sum[i-1] downto 0 do inc(ans,f[j]);    //对满足不能放入物品i的区间进行求和,加入答案。


    for j:=c downto v[i] do f[j]:=f[j]+f[j-v[i]];    //把物品放入背包。


  end; writeln(ans);


end;


//============================================================================


begin


  readln(all);


  for i:=1 to all do


  begin write(i,' '); work; end;


end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值