C - Coins 多重背包

C - 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

当a[i]=2时,我要凑金额为4的钱数,当金额为3时,需要用到1个面值为2和1个面值为1的,当要凑面值为4的时候,就需要两个面值为2的,面值为2只有一个,并且已经被金额为3的占用,所以金额为4的就凑不成(num[2]>1 num[2]表示面值为2的使用的次数,超过题目给定的个数,所以凑不成)

背包 参考网址 ::::
https://blog.csdn.net/qq_38749759/article/details/77406397
https://www.cnblogs.com/xinsheng/archive/2013/12/04/3458362.html
https://blog.csdn.net/flyinghearts/article/details/5898183
https://blog.csdn.net/lxy767087094/article/details/54730613
https://blog.csdn.net/jerans/article/details/54916955
https://www.cnblogs.com/A-S-KirigiriKyoko/p/6036368.html
https://blog.csdn.net/na_beginning/article/details/62884939



#include<stdio.h> 
#include<string.h>
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
	int dp[100005];
	int a[1000],c[1000];
	int num[100005];
int main(){
int n,m,i,j;
while(scanf("%d %d",&n,&m)!=EOF && n&&m)
{
for(i=0;i<n;i++){
	scanf("%d",&a[i]);
}
for(i=0;i<n;i++){
	scanf("%d",&c[i]);
}
for(i=1;i<=m;i++){
	dp[i]=0;
}
dp[0]=1;
int cnt=0;
for(i=0;i<n;i++){
	for(j=0;j<=m;j++)
	 num[j]=0;
	for(j=a[i];j<=m;j++){
		if(!dp[j] && dp[j-a[i]] && num[j-a[i]]<c[i]){ //使用钱a[i]来凑钱j
//用金额a[i]凑金额j,如果不能正好凑成的话,j-a[i]就是为了凑金额j还所需要的金额
//num数组中,j代表我当前要拼凑的金额,a[i]代表的要用掉的金额,j-a[i]表示要凑金额为j的钱还需要用到的钱, 
			num[j]=num[j-a[i]]+1;
//num数组用来记录用的钱的个数,假设我要凑金额为3(j=3),我要用到金额为2的钱还要用到金额为1的钱,num数组记录金额钱数的使用次数
//如果大于给定的纸张的个数,就不能再凑,钱的数量不够用了。 
			dp[j]=1;//当前面值为j的金额已经拼凑出来了,就把这个金额标记 
			cnt++;//凑出来一种,cnt就加1,来记录凑出的种类个数 
		}
	}
}
printf("%d\n",cnt);
}
return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值