YT06-背包-1002—Piggy-Bank -(6.27日-烟台大学ACM预备队解题报告)

来源:互联网 发布:红警网络进不去 编辑:程序博客网 时间:2024/03/29 22:26

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

310 11021 130 5010 11021 150 301 6210 320 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;}


0 0
原创粉丝点击