POJ 1742 Coins 【可行性背包】【非原创】

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4

题意:给你n种面值的硬币,面值为a1...an,数量分别为c1...cn,求问,在这些硬币的组合下,能够多少种面值,该面值不超过m

 

思路:设d[i][j]——前i种硬币,凑成总值j时,第i种硬币所剩余的个数。(能否想到这样构造是个难点

   默认d[i][j] = -1,代表无法凑成总值j

   转移方程为,若d[i-1][j]≥0,代表前i-1种已能够凑成j,那么就不必花费第i种硬币,所以d[i][j] = c[i]

   否则就看d[i][j-a[i]]的值,显然如果j < a[i],那么d[i][j] = -1,否则d[i][j-a[i]] ≤ 0,代表此刻第i种硬币已使用完了,所以自然d[i][j] = -1;

   否则,d[i][j] = d[i][j-a[i]]-1;

   可以看到d[i][]的值只与d[i-1][]和d[i][]有关,所以我们可以采用一维数组的形式,从而能够节省内存空间。

 AC代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef unsigned long long ll;
 6 const int maxn = 1e3 + 10;
 7 const int inf = 0x3f3f3f3f;
 8 const int maxx = 1e5 + 10;
 9 int dp[maxx];
10 int a[maxn];
11 int c[maxn];
12 bool vis[maxx];
13 int main()
14 {
15     int n, m;
16     while(~scanf("%d %d", &n, &m),(n||m))
17     {
18 
19         memset(dp, -1, sizeof(dp));
20         for(int i = 1; i <= n; ++i)
21         {
22             scanf("%d", a+i);
23        //     printf("%d ", a[i]);
24         }
25         for(int i = 1; i <= n; ++i)
26         {
27             scanf("%d", c+i);
28         }
29         dp[0] = 0;
30         for(int i = 1; i <= n; ++i)
31         {
32             for(int j = 0; j <= m; ++j)
33             {
34                 if(dp[j] >= 0)
35                 {
36                     dp[j] = c[i];
37                 }
38 
39                 else if(j - a[i] >= 0 && dp[j - a[i]] > 0)
40                 {
41                     dp[j] = dp[j - a[i]] - 1;
42                 }
43             }
44         }
45         int ans = 0;
46         for(int i = 1; i <= m; ++i)
47         {
48          //   printf("%d ", dp[i]);
49             if(dp[i] >= 0) ++ans;
50         }
51         printf("%d\n",ans);
52     }
53     return 0;
54 }
View Code

 

 

转载博客:戳这里

转载于:https://www.cnblogs.com/zmin/p/9329328.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值