开学了,好长时间没写博客了哈,来个DP练练手吧。。。(瞬间霸气测漏啊!!)
题目大意:
给定金额,钞票种类,钞票数目。求能找开的不大于金额且与金额差最小的值。
这是一个多重背包问题,可以优化成01背包二进制(感谢背包九讲!!)。
下面是代码:
#include <stdio.h>
struct node
{
int x,y;
} mon[15];
const int inf=-1<<30;
int dp[100005];
int max1(int a,int b)
{
if(a>b)return a;
return b;
}
int main()
{
int cash,n;
while(scanf("%d%d",&cash,&n)!=EOF)
{
int i,j,k;
for(i=0; i<n; i++)
{
scanf("%d%d",&mon[i].y,&mon[i].x);// x:monye y:count
}
for(i=1; i<=cash; i++)
{
dp[i]=0;
}
dp[0]=0;
for(i=0; i<n; i++)
{
if(mon[i].x*mon[i].y>=cash)
{
for(j=mon[i].x; j<=cash; j++)
{
dp[j]=max1(dp[j],dp[j-mon[i].x]+mon[i].x);
}
}
else
{
k=1;
while(k<mon[i].y)
{
int sum=k*mon[i].x;
for(j=cash; j>=sum; j--)
{
dp[j]=max1(dp[j],dp[j-sum]+sum);
}
mon[i].y-=k;
k*=2;
}
int sum=mon[i].y*mon[i].x;
for(j=cash; j>=sum; j--)
{
dp[j]=max1(dp[j],dp[j-sum]+sum);
}
}
}
printf("%d\n",dp[cash]);
}
return 0;
}