- 原题如下:
Coins
Time Limit: 3000MS | Memory Limit: 30000K | |
Total Submissions: 32998 | Accepted: 11214 |
Description
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.
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种硬币,每种硬币的面值为Ai,数量分别有Ci个。问你能拼凑出小于等于m的多少种面值。
首先,若dp[i+1][j]为用前i种硬币能否拼出价值j的东西。也就是说存在用前i-1种硬币拼成j,j-Ai,j-2*Ai.....j-Ci*Ai的情况。(类似01背包)这样做时间复杂度太高,所以需要优化。经典的优化方式是,不光求出能否拼成,还求出拼成之后剩多少个该面值的硬币。若是不能拼成就记为-1.这样一来,复杂度就是O(nm)了。但是这样做还是不够好。需要空间太大,所以还需要用滚动数组记录结果。
代码如下
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <queue>
#include <ctype.h>
using namespace std;
#define MAXN 100010
#define INF 100000
int dp[MAXN];
int a[110],c[110];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<n;i++)
cin>>c[i];
memset(dp,-1,sizeof(dp));
int cnt=0;
dp[0]=0;
for(int i=0;i<n;i++)
for(int j=0;j<=m;j++)
{
if(dp[j]>=0)
dp[j]=c[i];
else if(j<a[i]||dp[j-a[i]]<=0)
dp[j]=-1;
else
dp[j]=dp[j-a[i]]-1;
}
for(int j=1;j<=m;j++)
if(dp[j]>=0)
cnt++;
printf("%d\n",cnt);
}
}