hdu 1114 Piggy-Bank 完全背包

March 28, 2013
Hdu DP

Piggy-Bank

Time Limit: 20001000 MS (Java/Others) Memory Limit: 6553632768 K (Java/Others) Total Submission(s): 6841 Accepted Submission(s): 3375

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.

完全背包,只不过要求的是最小值,同时也要把背包装满,这就要理解一下当要求把背包装满的时候,如何去初始化了。这里我把除了f[0]以外的所有f的值都初始化为MAX,这样的话,因为我每次都求的是最小值,所以呢,如果背包被装满了,最后的f[V]一定是比MAX小的,这样就OK了。 但是还有一个困惑,为什么初始化为600000000就得到0呢?数组f里面所有的都为0……很困惑……

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int MAX = 0x3f3f3f3f;
using namespace std;
int f[10000+10];
int main(void){
#ifndef ONLINE_JUDGE
  freopen("1114.in", "r", stdin);
#endif
  int E, T, F, N, p[510], w[510];
  scanf("%d", &T);
  while (T--){
    memset(f, MAX, sizeof(f));
    scanf("%d%d", &E, &F); int V = (F-E);
    f[0] = 0;
    scanf("%d", &N);
    for (int i = 1; i <= N; ++i) scanf("%d%d", p+i,w+i);
    for (int i =1; i <= N; ++i){
      for (int v = w[i]; v <= V; ++v){
        f[v] = min(f[v], f[v-w[i]] + p[i]);
      }
    }
    if (f[V] < MAX) printf("The minimum amount of money in the piggy-bank is %d.\n", f[V]);
    else printf("This is impossible.\n");
  }
  return 0;
}

还有一个困惑,再研究一下……

另外,还有一个很无语的事情,就是开始把输出的那一句话打错了一个字母,把in打成了is,WA了一次……次嗷……幸亏有经验,后来特意仔细查看了一下,没有浪费很多时间……

唉,发现了,知道为毛线那个会成0了,应该是memset函数的问题,我把内个MAX的值改成600000000,然后用for循环赋值,就OK了……像这种函数使用的细节,唉,还得注意啊,虽然我知道这里出现了问题,也经常用这个函数,但是还会出现这种问题,像这种基础的用法都没有了解深入……

另外,看了别人的代码,还有一种想法,就是不把其它的f[]赋值成无穷大,可以赋值成-1,就是一种标记的思想,想想挺有意思的,哈哈,贴代码:(据说是ambition神牛的,虽然我这种菜鸟还不认识人家……汗……)

#include<stdio.h>
int num[10001],w[500],v[500];
main()
{
    int n,m,e,f,t,i,j;
    for(scanf("%d",&t);t>0;t--)
    {
        scanf("%d%d",&e,&f);
        m=f-e;
        for(scanf("%d",&n),i=0;i<n;i++)
            scanf("%d%d",&v[i],&w[i]);
        num[0]=0;
        for(i=1;i<=m;i++)
            num[i]=-1;
        for(i=0;i<n;i++)
        {
            for(j=w[i];j<=m;j++)
            {
                if(num[j-w[i]]!=-1&&num[j]!=-1)
                {if(num[j-w[i]]+v[i]<num[j]) num[j]=num[j-w[i]]+v[i];}
                else if(num[j-w[i]]!=-1&&num[j]==-1)
                {num[j]=num[j-w[i]]+v[i];}
            }
        }
        if(num[m]!=-1)
        printf("The minimum amount of money in the piggy-bank is %d.\n",num[m]);
        else
            printf("This is impossible.\n");
    }
}

哈哈,跟我的代码一样长撒……恰巧都是30行……

comments powered by Disqus