Coins POJ - 1742 DP 背包

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     

给出硬币面额及每种硬币的个数,求从1到m能凑出面额的个数。   多组数据,每组数据前两个数字为n,m。n表示硬币种类数,m为最大面额,之后前n个数为每种硬币的面额,后n个数为相应每种硬币的个数。 (n<=100,m<=100000,面额<=100000,每种个数<=1000)


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
const int mod=1e9;
const int len=1e5+4;
int main()
{
	int n,m;
	while(cin>>n>>m&&n+m)
	{
		int a[105],b[105];
		for(int i=0;i<n;++i)
			cin>>a[i];
		for(int j=0;j<n;++j)
			cin>>b[j];
		ll dp[len]={1};
		ll sum=0;
		int used[len]={};
		for(int i=0;i<n;++i)
		{
			memset(used,0,sizeof(used));//used[j]表示如果可以达到j这种状态第i种数还剩下多少个 
			for(int j=a[i];j<=m;++j)
			{
				if(dp[j]==0&&dp[j-a[i]]==1&&used[j-a[i]]<b[i])//注意这里不能写用b[i]--来表示到j这种状态第i种数还剩下多少个 
				{
					dp[j]=1;
					used[j]=used[j-a[i]]+1;
				}
			}
		}
		ll ans=0;
		for(int i=1;i<=m;++i)
			if(dp[i])ans++;
		cout<<ans<<endl;
	}
} 

猜你喜欢

转载自blog.csdn.net/hutwuguangrong/article/details/80284567