您的位置:首页 > 其它

POJ1742——Coins 多重背包

2016-03-15 17:57 375 查看
原题如下:

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. 

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