YT06-揹包-1002—Piggy-Bank -(6.27日-煙臺大學ACM預備隊解題報告)

kewlgrl發表於2015-07-15

Piggy-Bank

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 17   Accepted Submission(s) : 8

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long time, there should be enough cash in the piggy-bank to pay everything that needs to be paid.

But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs!

Input

The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing two integers E and F. They indicate the weight of an empty pig and of the pig filled with coins. Both weights are given in grams. No pig will weigh more than 10 kg, that means 1 <= E <= F <= 10000. On the second line of each test case, there is an integer number N (1 <= N <= 500) that gives the number of various coins used in the given currency. Following this are exactly N lines, each specifying one coin type. These lines contain two integers each, Pand W (1 <= P <= 50000, 1 <= W <=10000). P is the value of the coin in monetary units, W is it's weight in grams.

Output

Print exactly one line of output for each test case. The line must contain the sentence "The minimum amount of money in the piggy-bank is X." where X is the minimum amount of money that can be achieved using coins with the given total weight. If the weight cannot be reached exactly, print a line "This is impossible.".

Sample Input

3
10 110
2
1 1
30 50
10 110
2
1 1
50 30
1 6
2
10 3
20 4

Sample Output

The minimum amount of money in the piggy-bank is 60.
The minimum amount of money in the piggy-bank is 100.
This is impossible.

Source

Central Europe 1999 


•這道題就相當於一個容量為V的揹包,開始時包裡已裝有重量為E的物體,然後有一些重量為W[i],價值為P[i]的錢,求裝滿揹包時用的最小錢數。 

•第一行為T個測試案例。每個測試案例開始行包含兩個整數E和F表示一個空的豬和豬裝滿硬幣的重量。兩個權重給定的以克為單位。沒有豬的重量超過10公斤,這意味著1<= E <= F <= 10000。在第二行中的每一個測試的情況下,是一個整數N(1 <= N <=500),表示硬幣的種類數量。接下來N行,每行代表一種硬幣,這些行包含兩個整數,P和W(1 <= P <= 50000,1 <= W<= 10000)。P是貨幣單位的硬幣的值,W是它的重量。
•3
•10 110
•2
•1 1
•30 50
•10 110
•2
•1 1
•50 30
•1 6
•2
•10 3
•20 4
•輸出:
• 如果最少的錢X可以達到使用硬幣和給定的總重量輸出“The minimum amount ofmoney in the piggy-bank is X.”,否則,如果不能達到重量,則輸出"This is impossible."

基本思路


這個問題非常類似於01揹包問題,所不同的是每種物品有無限件。也就是從每種物品的角度考慮,與它相關的策略已並非取或不取兩種,而是有取0件、取1件、取2件……等很多種。如果仍然按照解01揹包時的思路,令f[i][v]表示前i種物品恰放入一個容量為v的揹包的最大權值.按照每種物品不同的策略寫出狀態轉移方程:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k*c[i]<=v}
我們可以由此得出一維陣列的虛擬碼:
for i=1..N
   for v=0..V
       dp[v]=max{dp[v],dp[v-c[i]]+w[i]}
和01揹包問題不一樣之處在於完全揹包的內迴圈是正序的,01揹包的內迴圈逆序是為了保證每件物品只選一次,而完全揹包同種物品可以選無限次,所以在考慮“加選一件第i種物品”也就是當前揹包的時候,需要一個可能已選入第i種物品的子結果f[i][v-c[i]],在狀態f[i][v-c[i]]中已經儘可能多的放入物品i了,此時在f[i][v-c[i]]的基礎上,我們可以再次放入一件物品i此時也是在不超過揹包容量的基礎下,儘可能多的放入物品i
這道題是完全揹包的變形,要求在限定了重量的Bank中裝入儘可能少的錢數。一般的完全揹包是求裝入儘可能多的錢數。所以只需在初始化的時候做一下變形:將dp[0]= 0,其他的都初始化為無窮大即可。在求dp的時候,將max改為min就可以了。
#include <iostream>
using namespace std;
int min(int a,int b)
{
    return a<b?a:b;
}
int main()
{
    int T,e,f,n,i,j,w[501],p[501],dp[10000],v;
    cin>>T;
    while(T)
    {
        T--;
        cin>>e>>f;
        v=f-e;
        for(i=1; i<=v; i++)
            dp[i]=9999999;
        dp[0]=0;
        cin>>n;
        for(i=0; i<n; ++i)
            cin>>p[i]>>w[i];
        for(i=0; i<n; ++i)//硬幣種類
            for(j=w[i]; j<=v; ++j)//硬幣重量,當前狀態的重量
                dp[j]=min(dp[j],dp[j-w[i]]+p[i]);//取最小
        if(dp[v]==9999999)
            cout<<"This is impossible."<<endl;
        else
            cout<<"The minimum amount of money in the piggy-bank is "<<dp[v]<<"."<<endl;
    }
   return 0;

}


相關文章