2584: 蓝桥杯2020年省赛真题-数字三角形(全网最详细带图解java动态规划解析)

分类->蓝桥杯JAVA练习->真题

题目 2584: 蓝桥杯2020年第十一届省赛真题-数字三角形


 解题思路:

这道题是标准的动态规划类型题目,由传统的“数字三角形”改编的,加了一个条件“向左下走的次数与向右下走的次数相差不能超过 1

方法上我参考了c323u2bdfhttps://blog.csdn.net/qq_60212533/article/details/127138546

可以从上至下思考,也可以从下至上,这里将从上至下的方法

首先通过一个二维数组 a[][] 存储数字三角形

然后再用一个二维数组存储 amax[][]  每个数字的路径最大和

① 从第一行第一个开始分析,以下图为例:

 到7的最大路径就是它本身,因此amax[0][0]=a[0][0]

② 然后看最左边这一列,它比较特殊,以下图为例:

3,8,2的上一个路径只能是上一行同列的位置,把斜着的图(左图)换成数组表示(右图)更清晰

也就是说,当列(j)为0(第一列)时,amax[i][j] = a[i][j] +amax[i-1][j]

③ 再看其他数字,以下图为例:

 每个数字可以是其上一行对应列或者上一行左侧一列的分支,因此他的最大路径应该是这两个数中较大的那个分支走下来的

amax[i][j]=Math.max(a[i][j]+amax[i-1][j], a[i][j]+amax[i-1][j-1])

④ 综上所述,我们得到了方程,其代码形式如下:

		amax[0][0]=a[0][0];     //首行首列元素的最大路径长度为其自身
	
		for(int i=1;i<n;i++)
		{
			for(int j=0;j<=i;j++)
			{
				if(j==0)           //左侧的列特殊处理,只能是上一行对应列的分支
				{
					amax[i][j]=a[i][j]+amax[i-1][j];
				}
				else          //其他列则可能是上一行对应列或者上一行左侧的列的分支
				{
					amax[i][j]=Math.max(a[i][j]+amax[i-1][j], a[i][j]+amax[i-1][j-1]);
				}					
			}
		}

⑤ 输出最大路径

这里我们需要注意前面提到的本题的附加条件“向左下走的次数与向右下走的次数相差不能超过 1”,这也就意味着最后一步总是集中于最后一行的中间,不明白的同学可以看下图:

 根据奇数行和偶数行要分别讨论:

当为奇数行的时候,最后一步必定是最后一行的中心位置,只有这样才能保证“向左下走的次数与向右下走的次数相差不能超过 1”

而当三角形为偶数行的时候,最后一步就可能是中间两个数其中的一个,因为要最大值,所以输出二者之间大的那个

代码形式如下:

if(n%2==0)
{
	System.out.print(Math.max(amax[n-1][n/2],amax[n-1][n/2-1]));
}
else
{
	System.out.print(amax[n-1][n/2]);
}

整体代码如下所示:

import java.util.*;
public class Main 
{
	public static void main(String[] args)
	{
		Scanner sca=new Scanner(System.in);
		int n= sca.nextInt();
		int a[][]=new int[n][n];
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<=i;j++)
			{
				a[i][j]=sca.nextInt();
			}
		}
		int amax[][]=new int[n][n];
		
		amax[0][0]=a[0][0];     //首行首列元素的最大路径长度为其自身
	
		for(int i=1;i<n;i++)
		{
			for(int j=0;j<=i;j++)
			{
				if(j==0)           //左侧的列特殊处理,只能是上一行对应列的分支
				{
					amax[i][j]=a[i][j]+amax[i-1][j];
				}
				else          //其他列则可能是上一行对应列或者上一行左侧的列的分支
				{
					amax[i][j]=Math.max(a[i][j]+amax[i-1][j], a[i][j]+amax[i-1][j-1]);
				}					
			}
		}
		if(n%2==0)
		{
			System.out.print(Math.max(amax[n-1][n/2],amax[n-1][n/2-1]));
		}
		else
		{
			System.out.print(amax[n-1][n/2]);
		}
	
	}

}

总结:

对于动态规划类的问题,关键在于状态转移方程,从一些已确定的边界着手推导结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值