题意:给你一个总数的钱,然后给你一些有数目限制的钱,问用这些钱能否拼出这个总数的钱,如果不能就拼出最接近这个钱的数目。
算法思路:背包9讲中的 完全背包 转换成0 1 背包进行操作。dp动态规划。
代码:
#include <iostream>
using namespace std;
int w[1000000];
int v[1000000];
int max(int a,int b)
{
return a>b ? a : b;
}
int dp(int cash,int num)
{
int i,j;
memset(v,0,sizeof(v));
for(i=0;i<=num;i++) // 0 1 背包中的主要算法 取或者不取
for(j=cash;j>=w[i];j--) //
{
v[j]=max(v[j], v[j-w[i]]+w[i]);
}
return v[cash];
}
int main()
{
int cash,zongshu;
int num,money;
int j=0;
int beishu;
while(scanf("%d%d",&cash,&zongshu)!=EOF)
{
j=0;
while(zongshu--)
{
beishu=1;
scanf("%d%d",&num,&money);
while(1) //讲钱转换为1 2 4 8 的类型。这样可以得到所有的组合
{
if(num<= beishu )
{
w[j++] = money * num;
break;
}
else
{
w[j++] = money * beishu;
num = num - beishu;
beishu *= 2 ;
}
}
}
j--;
cout<<dp(cash,j)<<endl;
}
return 0;
}