一道DP的题目,还是一道多重背包的题目,第一次接触。
题意:有现今cash,和n种钱币,每种钱币有ni个,价值为di,求各种钱币组成的不超过cash的最大钱数
思路:可以转换为0/1背包和完全背包来做。
Memory: 648K Time: 16MS
Language: C++ Result: Accepted
#include <stdio.h>
#include <iostream>
#include <string.h> int cash,n; int num[100005],price[100005]; bool us[100005];
int user[100005]; void calc()
{
memset(us,false,sizeof(us));
us[0]=true;
for(int i=0;i<n;i++)
{
memset(user,0,sizeof(user));
for(int j=price[i];j<=cash;j++)
if(us[j-price[i]]&&!us[j]&&user[j-price[i]]<num[i]) //这是这个程序的重点,为什么j++,而不是j成倍的增加price倍,其实,这通过us[j-price[i]]和!us[j]就限制了,它只可以增加price倍,当增加的不是price的倍数时,us[j-price[i]]是假的,当j为2倍时,由于之前us[j]也就是us[price]被赋值为了ture,所以这个if语句成立。以此类推
{
us[j]=true;
user[j]=user[j-price[i]]+1;
}
}
} int main()
{
while(scanf("%d%d",&cash,&n)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d%d",&num[i],&price[i]);
calc();
for(int i=cash;i>=0;i--)
if(us[i])
{
printf("%d\n",i);
break;
}
}
return 0;
}