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));
}
}