1. 程式人生 > >動態規劃——硬幣問題

動態規劃——硬幣問題

package dynamic_programming;

/**
* @author Tom Qian
* @email [email protected]
* @github https://github.com/bluemapleman
* @date 2017年8月22日
*/

/* 問題:我們有無數個面值為1、3、5的硬幣,試問給定目標值n,如何用最少的1、3、5硬幣組合出n值。
*
* 思路:
* 動態規劃問題的解答分成兩步:1、定義狀態 2、找到狀態轉移方程
*
* 1、定義狀態
* 狀態描述的是子問題的解。而子問題顧名思義,是我們面對的原始問題的一個子問題,只要解決了這個子問題,那麼原始問題也能迎刃而解。
* 在硬幣問題中,原始問題是我們最少用多少個硬幣能組合出n值,那麼我們就往簡單一點想:最少用多少個硬幣能組合出n-1值呢?因為假設我們只有一元硬幣時,我們要組合出n值,獲得solutions(n),是不是隻需要知道solutions(n-1)即可,因為solutions(n)=solutions(n-1)+1,只要再拿一枚一元硬幣就ok。同樣繼續回推,solutions(n-1)=solutions(n-2)+1……
*
* (……..是不是有點遞迴的味道?而其實,動態規劃就是一種優化的遞迴方式。大概可以先這樣理解:遞迴需要重複對比較低層次的最優解進行計算,而動態規劃把不斷地把低階解給儲存起來,以備後面求解更高層次的最優解時使用,因此一般動態規劃的效率會比遞迴高一些)
*
* 你可能奇怪,這麼簡單的問題有什麼好推的?
* 而關鍵在於,絕大多數時候,我們有不只一個選擇(硬幣不會只有一種面值的) ,比如下面的程式碼闡述的是硬幣有1、3、5三種面值時所有對應的最少硬幣數解,這種情況下,當你想用動態規劃思路求solutions(n),你有三種選擇:
* 1. 拿一枚1元硬幣:choice1=solutions(n-1)(組合出n-1值的最少硬幣數)+1(1枚1元硬幣)
* 2. 拿一枚3元硬幣:choice2=solutions(n-3)(組合出n-3值的最少硬幣數)+1(1枚3元硬幣)
* 3 拿一枚5元硬幣:choice3=solutions(n-5)(組合出n-5值的最少硬幣數)+1(1枚5元硬幣)
* 這三種和硬幣種類一一對應的選擇,就是三種狀態/子問題的解。而接下來我們需要在三個解中作出一個抉擇–>選擇值最小的那個解,即硬幣數最少的情況,那麼顯然,可以表達為:solutions(n)=min(choice1,choice2,choice3).而這樣也就引出了下面一個問題:在不同狀態/子問題的解中抉擇的依據,即我們需要定義的狀態轉移方程。
* 上述的是一個一般性的情況,而這樣不斷回推,顯然我們的問題會被推演到最初始最簡單的一些問題的解,而它們是解決上一段中那些高層次問題解的基礎:當我們有1、3、5三種硬幣時,我們需要多少個硬幣組合出0值->0個(不需要拿硬幣出來),1值->1個,2值->2個。這三個解拍拍腦袋直接想出來,因為你只有用1元硬幣去組合這一種選擇,可是當面對n=3時,你有兩個選擇,1.再拿一枚1元硬幣 2.丟掉手裡兩枚1元硬幣,拿一枚3元硬幣 顯然後者是目標解。即此時,如上一段所屬,因為硬幣的可選數超過了1,我們開始需要做解的抉擇,即必須用到狀態轉移方程了!
*
* 2、找到狀態轉移方程
* 當我們面對兩種狀態(解)的選擇時,根據我們的問題,我們必須從中做出抉擇。顯然,這裡我們要找最少的

硬幣數,那麼當我們面對n=3時,我們需要的解即為:
*
* min(solution(3-1)+1,solution(3-3)+1)
*
* 顯然,拿一枚面值3的硬幣就行了,而我們在這兩個解之間抉擇出一個目標解的過程即為狀態轉移方程(此處是找出最小值)。
*
* 那麼總結一下:解硬幣問題的過程就變成了這樣:
*
* 我們從最簡單的狀態開始,目標值n=1,n=2,n=3….,而解出簡單狀態的過程需要我們用這樣的邏輯去處理:
* 當n==0時,直接把解solutions[0]置為0(不需要拿出硬幣)
* 當n>0時,看有無面值比當前n小或相等的硬幣?
* - 沒有的話,無解,solutions[n]=Integer.MAX_VALUE。
* - 有的話,比較min(solution(n-vj)+1) j=1,2,…,J所有面值硬幣數,即把所有可能的硬幣選擇解全部做比較,選出最小的那個。
*/

public class 硬幣問題
{
    public static int leastCoins(int goal,int []coins){
        if(goal==0)
            return 0;

    int [] solutions=new int[goal+1];

    for(int i=0;i<solutions.length;i++)
        solutions[i]=Integer.MAX_VALUE-10000;

    solutions[0]=0;


    for(int i=coins[0];i<=goal;i++){
        for(int j=0;j<coins.length;j++){
            if(coins[j]<=i && solutions[i-coins[j]]+1<solutions[i])
                solutions[i]=solutions[i-coins[j]]+1;
        }
    }

    return solutions[solutions.length-1];
}

public static void main(String[] args)
{
    int[] coins={1,3,5};
    for(int i=0;i<10;i++){
        System.out.println(leastCoins(i, coins));
    }

}

}

相關推薦

動態規劃——硬幣找零

max 關系 i++ 是否 coin fine 個數 names std   動態規劃問題,主要在於需要想清楚遞推關系,num[i][j]表示能使用 i 種硬幣時,得到 j 零錢的最優解。   想來就是首先假設只能使用第一種硬幣 1 ,那麽會得到num[ 1 : n] =

動態規劃-硬幣找零問題四種情況

題目1:給定陣列arr,arr中所有的值都是正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求組成aim的最少貨幣數。 舉例:  arr[5,2,3],aim=20。  4張5元可以組成20元,其他的找錢方案都要使

動態規劃 硬幣問題,求最大、最小可以組成一個錢數的數

核心思想:         在我們從 1 元開始依次找零時,可以嘗試一下當前要找零的面值(這裡指 1 元)是否能夠被分解成另一個已求解的面值的找零需要的硬幣個數再加上這一堆硬幣中的某個面值之和,如果這樣分解之後最終的硬幣數是最少的,

動態規劃-硬幣問題

有n種硬幣,面值分別為V1,V2,....,Vn,每種都有無限多。給定非負整數S,可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。 1<=n<=100 0<=S<=10000 1<=Vi<=S 輸入:硬幣的種類n,

動態規劃-硬幣組合數目

import java.util.Scanner; /* * 硬幣的型別有1角,2角,5角,給定一個數額n,多少種組合方式 */ //暴力解法 public class CashNum {

動態規劃 硬幣 POJ

總時間限制: 1000ms 記憶體限制: 262144kB 描述 宇航員Bob有一天來到火星上,他有收集硬幣的習慣。於是他將火星上所有面值的硬幣都收集起來了,一共有n種,每種只有一個:面值分別為a1,a2… an。 Bob在機場看到了一個特別喜歡的禮物,想買來送給朋友Alice,這個禮物的價格是X元。B

動態規劃-硬幣組合

1.問題描述        對於m個面值為v1,v2,vm的硬幣,組成錢數n,不限制硬幣的數量和位置,求這些硬幣,最多有多少種組合的結果剛好等於n。2.分析     n=x1*v1+x2*v2+....+xm*vm,{x1,x2,....,xm}就是其中的一種組合,定義l[i

動態規劃——硬幣問題

package dynamic_programming; /** * @author Tom Qian * @email [email protected] * @github https://github.com/bluemaplema

動態規劃-硬幣問題分析

什麼是動態規劃 上次對動態規劃已經有了個大概的分析。引用維基百科的話就是: dynamic programming is a me

洛谷P1450 [HAOI2008]硬幣購物 動態規劃 + 容斥原理

string -1 line sum mes 開始 clas 完全背包 預處理 洛谷P1450 [HAOI2008]硬幣購物 動態規劃 + 容斥原理 1、首先我們去掉限制 假設 能夠取 無數次 也就是說一開始把他當做完全背包來考慮 離線DP 預處理 復雜度 4*v

動態規劃_百煉4120 硬幣

amp 使用 兩種 部分 新的 tor color 不能 blog 1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <math.h> 4 #includ

java動態規劃硬幣問題

四種 ava exti 千萬 print light sca 小數 length 最近一直在研究動態規劃的問題。今天遇到了取硬幣問題。 其實動態規劃還是,我從底部向頂部,依次求出每個狀態的最小值,然後就可以標記上。 這道題目就是,假如有1,5,7,10這四種幣值的硬幣,我取

NYOJ 995 硬幣問題(經典動態規劃

硬幣找零 時間限制:1000 ms  |  記憶體限制:65535 KB 難度:3 輸入 輸入資料: 第 1 行,為 N 和 T,其中 1≤N≤50 為硬幣系統中不同硬幣數;1≤T≤100000 為需要用硬幣找零的總數。 第 2 行為 N 個數值不大於 65535 的

最少硬幣問題(動態規劃遞推式)

最少硬幣問題 時間限制(普通/Java) : 1000 MS/ 3000 MS          執行記憶體限制 : 65536 KByte總提交 : 247            測試

硬幣找零問題(動態規劃

硬幣找零(動態規劃) 問題介紹 給定指定的硬幣種類,面值為 1, 3, 5(在此具體化些),給定所找零的錢數 sum,給出最少的硬幣找零數,每個種類的硬幣無限使用。 問題分析 看到這問題,當時我想到用貪心演算法來求解,最後求解方案因為巧合對了,後來在網上看到動態

【習題詳解】動態規劃DP:硬幣遊戲 蛋糕

動態規劃DP硬幣蛋糕塔 硬幣 題目描述 農夫約翰的奶牛喜歡玩硬幣遊戲,因此他發明了一種稱為“Xoinc”的兩人硬幣遊戲。 初始時,一個有N(5 <= N <= 2,000)枚硬幣的堆疊放在地

硬幣找零--動態規劃入門

假設有幾種硬幣,如1、3、5,並且數量無限。請找出能夠組成某個數目的找零所使用最少的硬幣數。  #include<iostream> #include<math.h> #define INF 9999999 using namespace std; int m

小米 oj 硬幣比賽(思維+動態規劃

 硬幣比賽 序號:#47難度:困難時間限制:1000ms記憶體限制:10M 描述 有 n 個不同價值的硬幣排成一條線。有 A 與 B 兩個玩家,指定由 A 開始輪流(A 先手,然後 B,然後再 A..)從左邊依次拿走 1 或 2 個硬幣(不能不拿,也不能拿其他個數),直

斐波那契數列和階乘的尾函式優化,動態規劃解決最小硬幣找零和揹包問題

// 遞迴是一種解決問題的方法,它解決問題的各個小部分,直到解決最初的大問題。遞迴通常涉及函式呼叫自身 // 斐波那契數列尾呼叫優化 function fibonacci(n, acc1 = 1, acc2 = 1) { if (n === 1 || n === 2) { ret

硬幣問題——DAG模型上的動態規劃

硬幣問題 Description 有n種硬幣,面值分別為 V1,V2,…,Vn。每種都有無限多。給定非負整數S,問可以選用多少個硬幣,使得面值之和恰好為S?輸出硬幣數目的最小值和最大值。 1<=n<=100,0<=S<=10000,1<=Vi&l