我现在做的是第三专题编号为
简单题意:
给你n种面额不同的金币和每种金币的个数,求这些金币能组合成的面额在m内有多少种
解题思路:
对于每种硬币而言:
if 价值×数量>=m
then 取这种硬币的次数相当于无限制,可以考虑成完全背包
else
then 考虑成0-1背包(二进制优化),就是把这种硬币的value和num组合出0-1背包可能出现的状态
编写代码:
#include<iostream>
using namespace std;
int dp[100010];
int a[110],c[110];
int n,m;
void zeroOne(int c,int w)
{
for(int i=m;i>=c;i--)
dp[i] = max(dp[i],dp[i-c]);
}
void full(int c,int w)
{
for(int i=c;i<=m;i++)
dp[i] = max(dp[i],dp[i-c]);
}
void mul(int c,int w)
{
int temp;
if( c*w >= m )
full(c,w);
else
{
temp = w;
for(int i=1; i<=temp; i<<2)
{
zeroOne(i*c,i*w);
temp -= i ;
}
zeroOne(temp*c, temp*w);
}
}
int main()
{
while(1)
{
cin >> n >> m;
if (n == 0 && m == 0)
break;
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; i++)
cin >> a[i];
for(int j=1; j<=n; j++)
cin >> c[j];
dp[0] = 1;
for(int k=1; k<=n; k++)
mul(a[k], c[k]);
int count = 0;
for(int i=1; i<=m; i++)
if(dp[i] > 0)
count++;
cout << count << endl;
}
return 0;
}