PAT 1068 Find More Coins 01揹包

Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special requirement of the payment: for each bill, she must pay the exact amount. Since she has as many as 10​4​​ coins with her, she definitely needs your help. You are supposed to tell her, for any given amount of money, whether or not she can find some coins to pay for it.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive numbers: N (≤10​4​​, the total number of coins) and M (≤10​2​​, the amount of money Eva has to pay). The second line contains N face values of the coins, which are all positive numbers. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the face values V​1​​≤V​2​​≤⋯≤V​k​​ such that V​1​​+V​2​​+⋯+V​k​​=M. All the numbers must be separated by a space, and there must be no extra space at the end of the line. If such a solution is not unique, output the smallest sequence. If there is no solution, output "No Solution" instead.

Note: sequence {A[1], A[2], ...} is said to be "smaller" than sequence {B[1], B[2], ...} if there exists k≥1 such that A[i]=B[i] for all i<k, and A[k] < B[k].

Sample Input 1:

8 9
5 9 8 7 2 3 4 1

Sample Output 1:

1 3 5

Sample Input 2:

4 8
7 2 4 3

Sample Output 2:

No Solution

題意:給出N枚硬幣價值,要求找出面值和恰好爲M的硬幣序列,若有多個解則給出字典序最小的解。

按照01揹包問題求解:把硬幣看成是w=v(質量=價值)的物品,選取一部分物品塞滿容量爲M的揹包,使得總價值最大,若最大價值等於M則滿足題意,否則無解。其中質量和價值等價,只需要一個數組coins[i]表示即可。題目要求從小到大輸出coin組合,且多解時輸出字典序最小的解,因此需要將數組從大到小排序,依次選擇硬幣考慮是否放入揹包,當加入硬幣後價值>=原價值時,將該硬幣放入揹包(等號是因爲當出現相同的價值時,選取當前硬幣後的字典序一定比之前的小),並用數組selected[i][v]=1記錄選取該硬幣。dp數組求解完成後,利用selected數組從第n個硬幣開始倒着找出所有被選擇的硬幣。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class Main {
	
	static int maxn=10010,maxv=110;
	static int[] dp=new int[maxv];
	static Integer[] coins=new Integer[maxn];
	static boolean[][] selected=new boolean[maxn][maxv];
	
    public static void main(String[] args) throws IOException {
    	BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));

    	String[] line=reader.readLine().split(" ");
    	int N=Integer.valueOf(line[0]),M=Integer.valueOf(line[1]);
    	line=reader.readLine().split(" ");
    	for(int i=1;i<=N;i++) {
    		coins[i]=Integer.valueOf(line[i-1]);
    	}
    	//降序排列
    	Arrays.sort(coins, 1, N+1, Collections.reverseOrder());
    	for(int i=1;i<=N;i++) {
    		for(int v=M;v>=coins[i];v--) {
    			if(dp[v]<=dp[v-coins[i]]+coins[i]) {//選擇該硬幣後價值更大
    				dp[v]=dp[v-coins[i]]+coins[i];//更新
    				selected[i][v]=true;//選擇第i個硬幣
    			}else {//不選
    				selected[i][v]=false;
    			}
    		}
    	}
    	if(dp[M]!=M)//最大價值不滿足條件
    		System.out.println("No Solution");
    	else {
    		//查找最優路徑
    		int k=N,v=M;
    		while(k>=0) {//反向查找
				if(selected[k][v]) {
    				System.out.print(coins[k]);
					v-=coins[k];//剩餘價值
					if(v!=0)
    					System.out.print(" ");
						
				}
    			k--;
    		}
    	}
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章