算法筆記_045:幣值最大化問題(Java)


目錄

1 問題描述

2 解決方案

2.1 動態規划法

 


1 問題描述

給定一排n個硬幣,其面值均為正整數c1,c2,...,cn,這些整數並不一定兩兩不同。請問如何選擇硬幣,使得在其原始位置互不相鄰的條件下,所選硬幣的總金額最大。

 


2 解決方案

2.1 動態規划法

本文所寫代碼思想參考自《算法設計與分析基礎》第三版上一段講解,具體如下:

 

 

具體代碼如下:

package com.liuzhen.chapter8;

import java.util.ArrayList;

public class CoinRow {
    /*
     * 參數Money:給定硬幣組合面值數
     * 函數功能:以數組鏈表形式返回最大總金額硬幣組合的數組下標以及最大總金額,
     * 其中鏈表中最后一個元素為最大總金額,其它元素為硬幣組合數組下標
     */
    public ArrayList<Integer> getMaxSumCoin(int[] Money){
        ArrayList<Integer> list = new ArrayList<Integer>();
        if(Money.length == 1){             //當給定硬幣個數只有一個時,最大總金額即為該枚硬幣
            list.add(0);                   //存放硬幣位置
            list.add(Money[0]);            //存放硬幣總金額
            return list;
        }
        
        int[] tempMaxSum = new int[Money.length];     //用於存放遍歷到當前硬幣位置(從前到后遍歷)的最大總金額
        tempMaxSum[0] = Money[0];
        if(Money[0] < Money[1])
            tempMaxSum[1] = Money[1];
        else
            tempMaxSum[1] = Money[0];
        
        for(int i = 2;i < Money.length;i++){
            if(tempMaxSum[i-1] >= tempMaxSum[i-2] + Money[i])
                tempMaxSum[i] = tempMaxSum[i-1];
            else
                tempMaxSum[i] = tempMaxSum[i-2] + Money[i];
        }
        
        System.out.println("\n當前位置硬幣的最大金額:");
        for(int i = 0;i < Money.length;i++)
            System.out.print(tempMaxSum[i]+" ");
        //根據tempMaxSum數組元素,找出,最大金額的硬幣組合元素的數組下標
        for(int i = Money.length-2;i >=0;i--){
            int temp = tempMaxSum[i];
            if(temp < tempMaxSum[i+1]){
                list.add(i+1);             //存放最大金額硬幣組合元素數組下標
                temp = tempMaxSum[i+1] - Money[i+1];
                for(int j = 0;j < Money.length;j++){   //尋找到tempMaxSum數組(從小到大排序)中第一個等於temp值的元素
                    if(tempMaxSum[j] == temp){
                        i = j;
                        break;
                    }
                }
            }
        }
        if(Money[0] >= Money[1])      //不管怎樣選擇硬幣組合,在前兩枚硬幣中一定會選一枚
            list.add(0);
        else
            list.add(1);
        list.add(tempMaxSum[Money.length-1]);     //存放硬幣最大總金額
        return list;
    }
    
    public static void main(String[] args){
        CoinRow test = new CoinRow();
        int[] Money = {1,1,2,10,6,2,10,8,12};
        
        System.out.println("當前位置硬幣的金額:");
        for(int i = 0;i < Money.length;i++)
            System.out.print(Money[i]+" ");
        
        ArrayList<Integer> list = test.getMaxSumCoin(Money);
        
        System.out.println("\n最大總金額硬幣組合的數組下標依次為:");
        for(int i = 0;i < list.size()-1;i++)
            System.out.print(list.get(i)+" ");
        
        System.out.println("\n最大總金額硬幣組合的對象數組下標相應面值依次為:");
        for(int i = 0;i < list.size()-1;i++)
            System.out.print(Money[list.get(i)]+" ");
        
        System.out.println("\n"+"最大總金額為:");
        System.out.println(list.get(list.size()-1));
    }
}

運行結果:

當前位置硬幣的金額:
1 1 2 10 6 2 10 8 12 
當前位置硬幣的最大金額:
1 1 3 11 11 13 21 21 33 
最大總金額硬幣組合的數組下標依次為:
8 6 3 0 
最大總金額硬幣組合的對象數組下標相應面值依次為:
12 10 10 1 
最大總金額為:
33

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM