蓝桥杯动态规划:数字三角形

蓝桥杯动态规划:数字三角形

这题是第十一届蓝桥杯省赛的试题H,当时比赛的时候自己也是菜鸟一枚,当然现在也还是…

下面是题目:
在这里插入图片描述
在这里插入图片描述
这是一个典型的动态规划算法题。
解题思路:
样例输入
5
7
8 1
2 7 4

先划分子问题。最终状态是到数字塔低端,所以我们自下而上逐层决策。对于倒数第二层8 1,8和1dou有可能走到,那么走到8或1的时候再向下走,我们肯定选择值最大的路径走,比如走到8,我们会选右下方的7,因为左下方的2比右下方的7小,1同理也会选7,因为7比4小。所以子问题解决了,我们可以合并最后一层和倒数第二层,直到将n层数塔问题变成二层数塔问题再变成一层数塔问题也就是答案了:
二层数塔
7
15 8
当得到最后一个子问题也就是二层数塔问题的时候答案就出来了,肯定选左下方的15,也就是最大值为7+15=22.这部分的算法就是如下代码,从倒数第二层开始,逐层合并,最后输出chs[0][0]就是答案了。

for (int i = n - 2; i >= 0; i--)
			for (int j = 0; j < i + 1; j++)
				chs[i][j]+=Math.max(chs[i+1][j],chs[i+1][j+1]);
					到这里我们只解决了寻找最大路径的值的问题,没有解决向左下方走和向右下方走的次数相差不能超过1的问题。
					下面我们来解决它
					思路:
					先看下面两张图

在这里插入图片描述
在这里插入图片描述
以五层和六层数塔为例,想要向左下方走和向右下方走的次数相差不能超过1就不能走红线圈中的路径里。多画图就知道为什么了。
代码思路就是从键盘获取数塔到数组中后,把红圈对应的数组元素置为零就可以了。用for循环来赋值。红圈对应的数组的纵坐标大于n/2+1,横坐标除开大于当前横坐标i/2和小于当前横坐标i/2的就行了,也就是除了中间的都是要置为零的。

for (int i = n - 1; i > n / 2 + 1; i--)
			for (int j = 0; j < i; j++) {
				if(j<i/2||j>i/2)chs[i][j] = 0;
				else continue;
			}
		我只简单实现,没有做代码简化,也没有测试很多用例,原因嘛,因为我懒。可能有错可能不够好,仅供参考。
		下面是完整的代码:
static int chs[][];

public static void main(String[] args) {
	M();
}

public static void M() {
	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	chs = new int[n][n];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < i + 1; j++)
			chs[i][j] = sc.nextInt();//从键盘获取数塔
	sc.close();
	for (int i = n - 1; i > n / 2 + 1; i--)
		for (int j = 0; j < i; j++) {
			if(j<i/2||j>i/2)chs[i][j] = 0;//把不能经过的路径置为零
			else continue;//其余的不动
		}
	for (int i = n - 2; i >= 0; i--)
		for (int j = 0; j < i + 1; j++)
			chs[i][j]+=Math.max(chs[i+1][j],chs[i+1][j+1]);//合并数塔,解决子问题
			
	System.out.println("最大路径值为:" + chs[0][0]);//输出答案
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值