POJ 1276 Cash Machine (多重背包)

7 篇文章 0 订阅
题意:我现在要从ATM中取钱,(ATM机中能取出的钱数最多为M)ATM里面有若干种货币,每一种都有对应的货币面额和张数。

问现在ATM能够取出来的 小于等于M的最大金额。

分析:若将M理解为背包体积(V ),而每种货币的面额理解成 value,货币的面额同样理解成cost,那么这个问题就是一个多重背包问题。

#include <stdio.h>
#include <limits.h>
#define MAX_CASH  100000
#define N 10
#define max(a,b) ((a)>(b)?(a):(b))
int V ;
int n ;
int dp[MAX_CASH+5] ;
int spend[N+5] ;
int sum[N+5] ;

void Restart_DP ( )
{
    int i ;
    for ( i = 0 ; i <= V ; i ++ )
    {
        dp[i] = 0 ;
    }
}


void ZeroOnePack ( int const cost , int const value )
{
    int i ;
    for ( i = V ; i >= cost ; i -- )
    {
        dp[i] = max ( dp[i] , dp[i-cost] + value ) ;
    }
}

void CompletePack ( int const cost , int const value )
{
    int i ;
    for ( i = cost ; i <= V ; i ++ )
    {
        dp[i] = max ( dp[i] , dp[i-cost] + value ) ;
    }
}

void MultiplePack ( int const cost , int const value , int amount )
{
    if ( amount * cost > V )
    {
        CompletePack ( cost , value ) ;
    }
    else
    {
        int k ;
        for ( k = 1 ; k < amount  ; k *= 2 )
        {
            ZeroOnePack ( k * cost , k * value ) ;
            amount -= k ;
        }
        if ( amount ) ;
        {
            ZeroOnePack ( cost * amount , value * amount ) ;
        }
    }
}

void DP_Solve ( int const n )
{
    int i ;
    for ( i = 1 ; i <= n ; i ++ )
    {
        int value , amount;
        value = spend[i] ;
        amount = sum[i] ;
        MultiplePack ( spend[i] , value , amount ) ;
    }
    printf ("%d\n" , dp[V] ) ;
    Restart_DP ( ) ;
}

int
main ( )
{
    while ( EOF != scanf ("%d%d" , & V , & n ) )
    {
        int i ;
        for ( i = 1 ; i <= n ; i ++ )
        {
            scanf ("%d%d" , & sum[i] , & spend[i] ) ;
        }
        DP_Solve ( n ) ;
    }
    return 0 ;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值