soj 2749 The Fewest Coins

Description

Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays 
for his goods in such a way that the smallest number of coins changes hands, i.e., the number of 
coins he uses to pay plus the number of coins he receives in change is minimized. Help him to 
determine what this minimum number is.

FJ wants to buy T (1 ≤ T ≤ 10,000) cents of supplies. The currency system has N (1 ≤ N ≤ 100) 
different coins, with values V1, V2, ..., VN (1 ≤ Vi ≤ 120). Farmer John is carrying C1 coins of 
value V1, C2 coins of value V2, ...., and CN coins of value VN (0 ≤ Ci ≤ 10,000). The shopkeeper 
has an unlimited supply of all the coins, and always makes change in the most efficient manner 
(although Farmer John must be sure to pay in a way that makes it possible to make the correct change).

Input

* Line 1: Two space-separated integers: N and T.

* Line 2: N space-separated integers, respectively V1, V2, ..., VN coins (V1...VN).

* Line 3: N space-separated integers, respectively C1, C2, ..., CN

Output

* Line 1: A line containing a single integer, the minimum number of coins involved in a payment and 
change-making. If it is impossible for Farmer John to pay and receive exact change, output -1.

Sample Input

3 70
5 25 50
5 2 1

Sample Output

3

Hint

Input Details
Farmer John has 5x5 cent coins, 2x25 cent coins and 1x50 cent coin. His bill is 70 cents.

Output Details
Farmer John pays 75 cents using a 50 cents and a 25 cents coin, and receives a 5 cents coin in change, for a total of 3 coins used in the transaction.

Source

USACO December 06 Gold



//题意:要付T元,用自己身上的钱去付并且找回零钱,使这其中涉及到的金钱总个数最小
//思路:明显找回零钱的最大值为max-1(max为所有面值中的最大值) 付钱的最大值为m+max-1
//         那么可以先把找回零钱的个数最小求出来《用多重背包,我的方法是转换回0-1背包,幸好能AC,其实还//         有更优的多重背包解法,详见背包九讲》
//        再用多重背包求出付款大于m时所用的coin个数
//        最后对两者之和求出最少coin个数

#include <stdio.h>
#define INF (1<<25)
int f[11000],f1[120];
int v[110],c[110];
void memset(int m,int a[]);
int main()
{
    int n,m,i,max,k,j;

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        max=0;
        for(i=0;i<n;i++)
         {
             scanf("%d",v+i);
             if(max<v[i])max=v[i];
         }
        for(i=0;i<n;i++)
         scanf("%d",c+i);
        memset(max,f1);
        f1[0]=0;
        for(k=0;k<n;k++)
        for(j=0;j<max/v[k];j++)
           for(i=max;i>=v[k];i--)
                if(f1[i-v[k]]+1<f1[i])
                   f1[i]=f1[i-v[k]]+1;

        memset(m+max,f);
        f[0]=0;
        for(k=0;k<n;k++)
           for(j=0;j<(m+max)/v[k]&&j<c[k];j++)
               for(i=m+max;i>=v[k];i--)
                   if(f[i-v[k]]+1<f[i])
                       f[i]=f[i-v[k]]+1;
        int min=INF;
        for(i=m;i<=m+max;i++)
                if(min>f[i]+f1[i-m])min=f[i]+f1[i-m];
    
        if(min!=INF)
        printf("%d\n",min);
        else
        printf("-1\n");
    }
}

void memset(int m,int a[])
{
    int i;
    for(i=0;i<=m;i++)
      a[i]=INF;
}

posted on 2011-07-21 12:09  sleeper_qp  阅读(435)  评论(0编辑  收藏  举报

导航