编程之中接触到很多关于算法的知识,想来整理一番,算是对自己记忆的一个提醒
1.Coin11Problem 问题为:使用最少的三种面值为1,3,5的硬币组合出11元。
重要的是状态以及状态转移方程 d(i)=min{ d(i-vj)+1 },其中i-vj >=0,vj表示第j个硬币的面值;
package com.njit.dynamic_programming;
/**
* 使用最少若干的1,3,5硬币,组合出11元
*
* @author 邵鹏
* @version [V1.00, 2017年7月13日]
* @see [相关类/方法]
* @since V1.00
*/
public class Coin11Problem
{
public static void main(String[] args)
{
//状态以及状态转移方程
//d(i) d(i)=min{d(i-vj)+1} vj为硬币的值
int[] a ={1,3,5};
int[] dp =new int[12];
dp[0]=0;
for(int i=1;i<=11;i++){
dp[i]=i;
}
for(int i=1;i<=11;i++){
for(int j=0;j<3;j++){
if(i>=a[j] && dp[i-a[j]]+1<dp[i]){
dp[i]=dp[i-a[j]]+1;
}
}
}
System.out.println("最少需要"+dp[11]+"个硬币可以组成11");
// System.out.println(a[0]+" "+a[1]+" "+a[2]);
for(int i=1;i<=11;i++){
System.out.print(dp[i]+" ");
}
}
}
以上为特定11元
以下为推广
package com.njit.dynamic_programming;
public class Coin11ProblemCommonVersion
{
public static void main(String[] args)
{
//调用方法 在1 3 5 三个硬币中找出最少的组合方式 组成 sum 变量为输入的sum
int inputCoin=11;
int outputCoin= new Coin11ProblemCommonVersion().getMinCoin(inputCoin);
System.out.println("当总数为 "+inputCoin+" 时,最少的硬币数为:"+outputCoin);
int[] outputCoinArray =new Coin11ProblemCommonVersion().getMinCoinArray(inputCoin);
System.out.println("当总数为 "+inputCoin+" 时,各硬币数为:");
for(int i=1;i<=inputCoin;i++){
System.out.println("dp["+i+"]="+outputCoinArray[i]);
}
}
/**
* 根据输入,动态输出硬币数量
*
* @param sum
* @return
* @see [类、类#方法、类#成员]
*/
public int getMinCoin(int sum){
int coin=0;
int[] a ={1,3,5};
int[] dp = new int[sum+1];
dp[0]=0;
for(int i=1;i<=sum;i++){
dp[i]=i;
}
for(int i=1;i<=sum;i++){
for(int j=0;j<3;j++){
if(i>=a[j] && dp[i-a[j]]+1<dp[i] ){
dp[i]=dp[i-a[j]]+1;
}
}
}
return dp[sum];
}
/**
* 输入最后的硬币数,返回过程中的所有最小硬币数
* <功能详细描述>
* @param sum
* @return
* @see [类、类#方法、类#成员]
*/
public int[] getMinCoinArray(int sum){
int coin=0;
int[] a ={1,3,5};
int[] dp = new int[sum+1];
dp[0]=0;
for(int i=1;i<=sum;i++){
dp[i]=i;
}
for(int i=1;i<=sum;i++){
for(int j=0;j<3;j++){
if(i>=a[j] && dp[i-a[j]]+1<dp[i] ){
dp[i]=dp[i-a[j]]+1;
}
}
}
return dp;
}
}
2.MathTowerProblem (数塔问题:三角形结构,算出从下到上,数字总和最大的一条路径的和)
状态转移方程
f[i][j] = max(f[i+1][j], f[i+1][j+1]) + map[i][j]
int[][] mathTower = new int[][]{{0,0,0,0,0,0},{0,7,0,0,0,0},{0,3,8,0,0,0},
{0,8,1,0,0,0},{0,2,7,4,4,0},{0,4,5,2,6,5}};
System.out.println("原始节点为:");
for(int i=1;i<=5;i++){
for(int j=1;j<=i;j++){
System.out.print(mathTower[i][j]+" ");
}
System.out.println();
}
for(int i=5;i<=5;i--){
for(int j=1;j<i;j++){
mathTower[i-1][j]+=Math.max(mathTower[i][j], mathTower[i][j+1]);
}
}
System.out.println("自底而上的最大数值路径得到的值为: "+mathTower[1][1]);
for(int k=1;k<=5;k++){
for(int t=1;t<=k;t++){
System.out.print(" "+mathTower[k][t]);
}
System.out.println();
}