Poj 1742 Coins(多重背包)

一、Description

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch.
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.
二、题解
       这道题之前做过一道背包的题,但是当时觉得看不下去,就搁置了。做这道题时也没太多考虑背包,就是随着感觉做了一通,最后虽然做出来了,但是TLE。于是就狠心地看了背包的内容。参考了背包问题九讲背包之01背包、完全背包、多重背包详解 — TankyWoo,对照着看了一遍,渐渐有了感觉了。
       背包问题其实主体是动态规划,背包分为:

01背包(ZeroOnePack): 有N件物品和一个容量为V的背包,每种物品均只有一件第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 

完全背包(CompletePack): 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 

多重背包(MultiplePack): 有N种物品和一个容量为V的背包,第i种物品最多有n[i]件可用。每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 

        比较三个题目,会发现不同点在于每种背包的数量,01背包是每种只有一件,完全背包是每种无限件,而多重背包是每种有限件。
        关于背包的知识请点击上面的两个链接。
        对于这道题目呢,用到的是多重背包,即每种钱币有有限个。相对背包问题而言,此问题钱币有价值没有重量,它只有一个属性。而且不要求求出最大的值,只要求求出最多能构成几种价格。所以,这里用到了boolean 类型的dp数组记录,下标为价格,值为true表示可以由钱币构成,false则不行。至于具体实现,跟完全背包的实现差不多,内层循环采用顺序,但是不同的是要控制次数。
import java.util.Scanner;
public class Main{
  public static void main(String args[])
{
   int N, M;
   Scanner sc=new Scanner(System.in);
   while(sc.hasNext())
   {
      N=sc.nextInt();
      M=sc.nextInt();
      if(N==0&&M==0) 
    	  break;
      int a[]=new int[100];
      int c[]=new int [100];
      for (int i=0; i< N; i++) 
    	  a[i]=sc.nextInt();
      for (int i=0; i< N; i++) 
    	  c[i]=sc.nextInt();

      int nRes=0;
      boolean dp[]=new boolean[100001];
      dp[0]=true;

      for (int i=0; i< N; i++){
          int num[]=new int[100001];
          for (int j=a[i]; j<=M; j++){
             if (!dp[j] && dp[j-a[i]] && num[j-a[i]]< c[i]){
                   dp[j]=true;
                   num[j]=num[j-a[i]]+1;
                   nRes++;
              }
          }
      }
      System.out.printf("%d
", nRes);
   }
  } 
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/AndyDai/p/4734134.html