POJ 1276 Cash Machine
开学了,好长时间没写博客了哈,来个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; }