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;
}


posted @ 2013-09-04 20:11  、小呆  阅读(111)  评论(0编辑  收藏  举报