2.1.1問題描述
使用備忘錄的方法計算組合,例如計算C(n,k).
2.1.2程序使用說明
Java version:1.8.0_111
IDE:eclipse
直接運行CombinedCalculation.java文件,在控制檯查看結果。
2.1.3簡要分析和設計
此題主要步驟可以分爲兩個,遞歸的過程,記錄的過程,計算C(n,k)可以有兩種情況假設第一個因子存在於被選擇的K個點之中,則只需要在剩下的C-1個因子中選擇K-1個因子,假設第一個因子沒有存在於K個被選因子中,則需要計算在C-1個因子中選擇K個元素。則遞歸表達式可以寫成
公式1
上面分析的是遞歸的過程,下面分析備忘錄記錄的過程,在程序最開始的時候創建一個矩陣,此處矩陣在程序中的表現爲一個二維數組大小爲R(n*k),在計算C(N,K)之前先判斷二維數組中是否已經存在該值,如果存在,則將該值直接返回回去若不存在,則使用上面的遞歸表達式計算該值。並保存在數組n,k位置。
僞代碼:
輸入:需要求解問題c(i,j)中的i,j
輸出:問題解出c(i,j)的值
Memorand(M[1...n,1...n],i,j)
If(M[i][j]<0)
M[i][j]=Memorand(M[1...n,1...n],i-1,j)+Memorand(M[1...n,1...n],i-1,j-1)
Return M[i][j]
2.1.4測試用例
測試用例一:(8,1)
結果:8
測試用例二:(8,0)
結果:1
測試用例三:(-8,1)
結果:0
測試用例四:(8,-1)
結果:0
測試用例五:(8,2)
結果:28
2.1.5源代碼:
此題使用了三種方法寫。
方法一:使用公式計算
方式二:使用遞歸備忘錄方式計算
代碼:
package one.one;
/**
* 計算組合
* @author ym
*/
public class CombinedCalculation {
/**
* 備忘錄
* @param Memorandum
* @param n
* @param k
* @return
*/
public int Memorandum(int[][]Memorandum,int n,int k){
if(n<0||k<0){
return 0;
}
if(Memorandum[n][k]<0){
if(k==0){
Memorandum[n][k]=1;
}
else{
Memorandum[n][k]=Memorandum(Memorandum,n-1, k-1)
+Memorandum(Memorandum, n-1, k);
}
}
return Memorandum[n][k];
}
/**
* 備忘錄方式
* @param n
* @param k
* @return
*/
public int calculate3(int n,int k){
if(n<0||k<0){
return 0;
}
int[][] Memorandum = new int[n+1][k+1];
for(int i=0;i<Memorandum.length;i++){
for(int j=0;j<Memorandum[0].length;j++){
Memorandum[i][j]=-1;
}
}
return Memorandum(Memorandum,n, k);
}
public static void main(String[]args) {
CombinedCalculation CC = new CombinedCalculation();
//測試方式一
System.out.print(CC.calculate3(8, 1));
System.out.print(" "+CC.calculate3(8, 0));
System.out.print(" "+CC.calculate3(-8, 1));
System.out.print(" "+CC.calculate3(8, -1));
System.out.print(" "+CC.calculate3(8, 2));
}
}