动态规划-数字三角形(递归+递推+空间优化)

题目

/*
 *     7
 *   3   8
 *  8  1  0
 * 2  7  4  4  
 *4  5  2  6  5 
 *数字三角形
 *题目:
 *在上面的三角形中,找一条从顶部到底边的路径,往左下或者右下走
 *求路径所经过数字之和最大
 *三角形行数1~100,数字为0~99
 *
 *输入:(以直角方式输入)
 *5//行数
 *7
 *38
 *810
 *2744
 *45265
 *
 注:输入时数字间有空格

1.递归(未记录每次MaxSum(r,j),多次重复计算)

*法1(时间复杂度很大)
*分析:
*1.用二维数组存放三角形D
*2.D(r,j)下一步D(r+1,j),或者D(r+1,j+1)
*3.MaxSum(r,j),从D(r,j)到底边各路径中最佳路径长
*递推式如下:
*if r==N MaSum(r,j)=D(r,j)
*if r<N  MaxSum(r,j)=Max(MaxSum(r+1,j),MaxSum(r+1,j+1))+D(r,j)
*
*/

package dynamic_program;
import java.util.Scanner;
public class Test_11 {

   public static int MaxSum(int i,int j)
   {
   	if(i==n)
   		return D[i][j];
   	int x=MaxSum(i+1,j);
   	int y=MaxSum(i+1,j+1);
   	return Math.max(x, y)+D[i][j];
   				
   }
   
   static int [][]D=new int [101][101];
   static int n;
   static Scanner in=new Scanner(System.in);
   public static void main(String[] args) {
   	// TODO Auto-generated method stub
   
   	int i,j;
   	n=in.nextInt();
   	for(i=1; i<=n; i++)
   		for(j=1;j<=i;j++)
   		{
   			D[i][j]=in.nextInt();
   		}
   	System.out.println(MaxSum(1,1));

   }

}

2.递归+动态规划(记录每个位置的Maxsum(r,j),避免重复计算)

package dynamic_program;
import java.util.Scanner;
/*
 * 数字三角形法2
 * 改进:
 * 每算一个MaxSum(r,j)就保存起来,避免重复计算,MaxSum为二维数组
 * 记忆递归型动态规划
 */
public class Test_12 {
	public static int MaxSum(int i,int j)
	{
		if(maxSum[i][j]!=-1)
			return maxSum[i][j];//已经被算过,直接返回
		if(i==n)
			maxSum[i][j]=D[i][j];
		else{
			
			int x=MaxSum(i+1,j);
			int y=MaxSum(i+1,j+1);
			maxSum[i][j]=Math.max(x, y)+D[i][j];
		}
		return maxSum[i][j];
					
	}
	static int D[][]=new int[101][101];
	static int [][]maxSum=new int[101][101];
	static int n;
	static Scanner in=new Scanner(System.in);
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		int i,j;
		n=in.nextInt();
		for(i=1; i<=n; i++)
			for(j=1;j<=i;j++)
			{
				D[i][j]=in.nextInt();
				maxSum[i][j]=-1;//表示还没有被算出来
			}
	}
}

3.递归转递推,从底边往上推算

package dynamic_program;
import java.util.Scanner;

/*
 * 数字三角形递归转递推,由已知推未知
 * 自下而上的推算
 * 优化1:用一维数组maxSum就可以存放,每次将上一行的最佳路径覆盖左下数据
 * 优化2:直接用D数组的最后一行代替maxSum数组
 */
public class Test_13 {
//递推
	static int D[][]=new int[101][101];
	static int [][]maxSum=new int[101][101];
	static int n;
	static Scanner in=new Scanner(System.in);
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		int i,j;
		n=in.nextInt();
		for(i=1; i<=n; i++)
			for(j=1;j<=i;j++)
			{
				D[i][j]=in.nextInt();
			}
		
		//最后一行的最佳路径即本身
		for(i=1;i<=n;i++)
			maxSum[n][i]=D[n][i];
		
		for(i=n-1;i>=1;i--)
			for(j=1;j<=i;j++)
				maxSum[i][j]=Math.max(maxSum[i+1][j], maxSum[i+1][j+1])+D[i][j];
		System.out.println(maxSum[1][1]);
	}
}

public class Test_14 {
//优化1+优化2
	static int D[][]=new int[101][101];
	static int n;
	static Scanner in=new Scanner(System.in);
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int i,j;
		n=in.nextInt();
		for(i=1; i<=n; i++)
			for(j=1;j<=i;j++)
			{
				D[i][j]=in.nextInt();
			}
		int []maxSum=D[n];
		for(i=n-1;i>=1;i--)
			for(j=1;j<=i;j++)
				maxSum[j]=Math.max(maxSum[j], maxSum[j+1])+D[i][j];
		System.out.println(maxSum[1]);
	}
}
运行结果:
30

总结:动态规划适用于求最优解时,其子问题也是最优的情况,并且每一状态可以支撑其后状态(子问题可以支撑下一个问题的解决)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值