您的位置:首页 > 其它

ACM: 动态规划题 poj 3093 0-1背包

2016-05-19 23:25 387 查看
[align=center]Margaritas on the River Walk[/align]
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

 

题意: 从n个物品选出一部分, 使它们的值累加起来Sum,如果Sum+a[i]任何一个不在Sum之内的值,

     
将大于限制S. 问有多少种可能组合.

解题思路:

     
1. 从物品中选取一部分出来, 先将全部按值从小到大排序. 进行背包问题求解.

        
设sum[i]表示前i个排序后值的和, 并且假设a[i]是当前最小不能再放进去的值.

        
即: 前i-1种物品都必须已经放进去了. dp[ sum[i-1] ] = 1

     
2. 我们知道背包的临界值是S(最大值), 并且假设sum[i-1]物品已经在背包中了,

         之后枚举后面的物品即可.
范围区间[ sum[i-1]+a[j] , S ]; (j
> i)

 

代码:

#include <cstdio>

#include <iostream>

#include <cstring>

#include <algorithm>

using namespace std;

#define MAX 1005

#define MAXSIZE 32

int n, S;

int sum[MAXSIZE], a[MAXSIZE];

int dp[MAXSIZE*MAX];

inline int max(int a, int b)

{

 return a > b ? a : b;

}

int DP()

{

 int result = 0;

 for(int i = 1; i <= n; ++i)

 {

  if(sum[i-1] > S)
break;

  memset(dp, 0,
sizeof(dp));

  dp[ sum[i-1] ] = 1;

  for(int j = i+1; j
<= n; ++j)

  {

   for(int k =
S; k >= sum[i-1]+a[j]; --k)

    dp[k]
+= dp[ k-a[j] ];

  }

  int temp = max(sum[i-1],
S-a[i]+1);

  for(int p = temp; p
<= S; ++p)

   result +=
dp[p];

 }

 return result;

}

int main()

{

// freopen("input.txt", "r", stdin);

 int caseNum, num = 1, i;

 scanf("%d", &caseNum);

 while(caseNum--)

 {

  scanf("%d %d",
&n, &S);

  for(i = 1; i <=
n; ++i)

   scanf("%d",
&a[i]);

  sort(a+1, a+n+1);

  if(a[1] >
S)

  {

   printf("%d
%d\n", num++, 0);

   continue;

  }

  sum[0] = 0;

  for(i = 1; i <=
n; ++i)

   sum[i] =
(sum[i-1]+a[i]);

  printf("%d %d\n", num++,
DP());

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: