Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 28   Accepted Submission(s) : 12

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

In the country of ALPC , Xiaoqian is a very famous mathematician. She is immersed in calculate, and she want to use the minimum number of coins in every shopping. (The numbers of the shopping include the coins she gave the store and the store backed to her.)
And now , Xiaoqian 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). Xiaoqian 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 .But Xiaoqian is a low-pitched girl , she wouldn’t like giving out more than 20000 once.

Input

There are several test cases in the 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
The end of the input is a double 0.

Output

Output one line for each test case like this ”Case X: Y” : X presents the Xth test case and Y presents the minimum number of coins . If it is impossible to pay and receive exact change, output -1.

Sample Input

3 70
5 25 50
5 2 1
0 0

Sample Output

Case 1: 3

一个人拿>=t的钱去买价值为t的东西,给出了拿的钱的面值和数量,用多重背包处理加上二进制优化就可以解决了。

商家找钱,>t时商家要找钱i-t,商家的钱的数量视为无限,用完全背包,最后人和商家的交易中钱的数量最少的情况。

dp[i]=k;i表示当前钱的金额,k表示构成当前金额目前为止需要的最少钱的数量。

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
#define inf 0x7777777
const int maxn=20000;
const int N=150;
int v[N],c[N];
int dp1[maxn+1],dp2[maxn+1];
int min(int a,int b)
{
    return a<b?a:b;
}
void onepack(int a,int w)
{
    a=a*w;
    for(int i=maxn;i>=a;i--)
    {
        dp2[i]=min(dp2[i],dp2[i-a]+w);
    }
}
void allpack(int a)
{
    for(int i=a;i<=maxn;i++)
    {
        dp2[i]=min(dp2[i],dp2[i-a]+1);
    }
}
void mulpack(int a,int w)
{
    if(a*w>=maxn)
    {
        allpack(a);
        return ;
    }
    int cnt=1;
    while(cnt<w)
    {
        onepack(a,cnt);
        w-=cnt;
        cnt*=2;
    }
    onepack(a,w);
}

int main()
{
    int n,t;
    int cas=0;
    while(cin>>n>>t,n||t)
    {
        cas++;

        for(int i=1; i<=n; i++)
            cin>>v[i];
        for(int j=1; j<=n; j++)
            cin>>c[j];

        for(int i=1; i<=20000; i++)
            dp2[i]=inf,dp1[i]=inf;//我刚开始直接用memset,答案一直不对,长记性!!
        dp2[0]=0,dp1[0]=0;
        for(int i=1; i<=n; i++)
            for(int j=v[i]; j<=maxn; j++)
            {
                dp1[j]=min(dp1[j],dp1[j-v[i]]+1);
            }
        for(int i=1;i<=n;i++)
        {
            mulpack(v[i],c[i]);
        }
        int ans=inf;
        for(int i=t;i<=20000;i++)
        {
            if(dp2[i]!=inf&&dp1[i-t]!=inf)
                ans=min(ans,dp1[i-t]+dp2[i]);//dp1表示商家,dp2表示人,最后自己没注意,wa了好几次;
        }
        cout<<"Case "<<cas<<": ";
        if(ans==inf) cout<<"-1"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}