1. 程式人生 > >動態規劃解決整數劃分的問題

動態規劃解決整數劃分的問題

前幾天去華為做機試,遇到一個整數劃分的問題,題目是:現有1,2,5,10,20,50,100 元這幾種錢幣,問給定n元能有多少種分配方式。例如n=4時,有1+1+1+1  ,1+2+1 , 2+2 三種劃分。我解決這道題是從網上看的方法,用的遞迴,但是悲劇的是測試用例執行超時,結果題沒做出來,我直覺上覺得用動態劃分可以解決,所以就研究了動態劃分的解法。

首先,先找出劃分,每種組合以最大面值等於多少就形成一個劃分:
例如:現在這道題,有 1 , 2 , 5 ,10 ,20 ,50 , 100這7種劃分,每種劃分的定義是,m劃分代表,在這些錢幣中,最大的錢幣為m。

找出劃分後再找出遞推公式,這個遞推公式在網上找,一大堆,但是針對這個問題的遞推公式為:
        n代表錢數,m代表劃分數
        1. 當n==1或者是m==1時,q(n , m)=1;
        2. 當n==m時,q(n ,  m)=q(n,m-1)
        3. 當n<m時,q (n , m)=q(n,n)
        4. 當n>m時,q(n , m)= q(n ,m-1)+q(n-m,m)i

然後找出初始條件,初始條件就是當n==0,時,所有劃分都等於0,所以再二維陣列的第一行都為0,二維陣列,行代表你的錢數,列數代表的劃分數,這些劃分的值在一個一維陣列中存著,所以二維陣列的列代表,上面一維陣列的索引。還有就是當1劃分的時候,所有值都等於1(二維陣列的值就是拆分的個數)。

然後就按照上面的遞推公式來填充二維陣列,最後返回你錢數的最大劃分就是最終結果,我是根據01揹包問題研究的這道題,如有不懂請參見經典的01揹包問題,如寫的不好,請大家多批評,下面是我的程式碼:直接可以執行出結果

package com.test;

public class Main {

static int[] qian=new int[]{1,2,5,10,20,50,100};

public static int get(int money){
int[][] test=new int[money+1][7];
for(int i=0;i<test.length;i++){
if(i==0){
for(int j=0;j<qian.length;j++){
test[i][j]=0;
}
}else{
for(int j=0;j<qian.length;j++){
if(qian[j]==1){
test[i][j]=1;
}else{
if(i<qian[j]){
test[i][j]=test[i][j-1];

}else if(i==qian[j]){
test[i][j]=test[i][j-1]+1;
}else if(i>qian[j]){
test[i][j]=test[i-qian[j]][j]+test[i][j-1];
}
}
}
}
}
for(int i=0;i<=money;i++){
for(int j=0;j<qian.length;j++){
System.out.print(test[i][j]+" ");
}
System.out.println();
}
return test[money][qian.length-1];
}
public static void main(String[] args) {
System.out.println(get(250));

}

}
更多
0