题意:给你价值为a1,a2.....的货币,每种有c1,c2.......个,求这些货币所能组成的价值小于等于m有多少个.....
思路:很像一道多重背包题?那我一开始的确是用多重背包的思路编写的......TLE了,原来其中隐藏着一个被我忽视的一个问题,当ai*ci>=m时,我们没有必要去拆分ci了,就直接把这种情况当作完全背包处理.......
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[100005],t[300][2];
int n,m;
int sum;
void deal1(int x)
{
for(int j=m;j>=x;j--)
if(dp[j-x]&&dp[j-x]+x>dp[j]&&dp[j-x]+x-1<=m)
{
if(!dp[j]) sum++;
dp[j]=dp[j-x]+x;
}
}
int main()
{
while(scanf("%d%d",&n,&m)>0&&(n+m))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i][0]);
}
memset(dp,0,sizeof(dp));
dp[0]=1;
sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i][1]);
if(t[i][1]*t[i][0]<m)
{
int k=1;
while(t[i][1]-k>0)
{
deal1(k*t[i][0]);
t[i][1]-=k;
k*=2;
}
deal1(t[i][1]*t[i][0]);
}
else
{
for(int j=t[i][0];j<=m;j++)
if(dp[j-t[i][0]]&&dp[j]<dp[j-t[i][0]]+t[i][0])
{
if(!dp[j]) sum++;
dp[j]=dp[j-t[i][0]]+t[i][0];
}
}
}
printf("%d
",sum);
}
return 0;
}