蓝桥杯-DP入门1

动态规划--并不是特定的算法,是一种思想;通常需要整理出一个递推式,如:f(i)=g(i-1)+g(i-2),每一个i称为一个状态,每个状态只跟前面的状态有关系;

跟高中学的递推式是一样的吧。。


题目一:

如这样的三角形:

第一行n为行数;

接下来三行为每层三角形的数字排列;规则是:从第一层往下 每次可以往左或者往右,输出经历点数字和最大的那个;

输出 27

3
9
9 1
9 2 9
27

分析:可以从上往下,也可以从下往上;

这道题从底层往上走;

对三角形用二维数组a[][]记录;a[1][1]代表第一层第一个数字;例子a[3][1]为第三层的第一个数组9;

则 定义一个状态dp[i][j],表示在第i层第j列的已经经过的最大数字;注意是从下往上;

dp[3][1] =9 (只能为9);dp[3][2]=2;dp[3][3]=9;

则dp[2][1] = a[2][1] + max{dp[3][1],dp[3][2]};dp[2][2]=....

所以递推式为:

dp[i][j] = Math.max{dp[i+1][j]+dp[i+1][j+1]}+a[i][j];

自然 最顶层的就是最大的数字和了;


import java.util.Scanner;

public class 捡水果 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int a[][] = new int[n+1][n+1];
		int dp[][] = new int[n+1][n+1];
		for (int i = 1; i < n+1; i++) {
			for (int j = 1; j <= i; j++) {
				a[i][j] = input.nextInt();
			}
		}
		input.close();
		for (int i = 1; i < n+1; i++) {
			dp[n][i] = a[n][i];
		}
		for (int i = n-1; i >0; i--) {
			for (int j = 1; j <= i; j++) {
				dp[i][j] = Math.max(dp[i+1][j], dp[i+1][j+1])+a[i][j];
			}
		}
		System.out.println(dp[1][1]);
	}
}


题目二:

计蒜客-蒜头跳木桩:

说有一列树桩:高低不一;如:9 5 8 3 9 4 1

只能跳比等于或小于当前木桩高度;不能回头跳;

问你选一个木桩来跳能跳到最多的木桩;


分析:

如用dp[i]来记录一个状态;看例子:假如跳到8,必然是从9跳过去的;dp[8] = dp[9] + 1;

假如跳到3;那么可能是从9,5,8跳过去的;dp[8] = dp[j] + 1; j为之前比3大的所有数;

则递推式:dp[i]=max{dp[j],j=...}+1;j之前比i都高或者等于的木桩;遍历可得。。

import java.util.Scanner;

public class 蒜头跳木桩 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int high[] = new int[n+1];
		for (int i = 1; i < high.length; i++) {
			high[i] = input.nextInt();
		}
		
		int dp[] = new int[n+1];
		for (int i = 1; i < high.length; i++) {
			int position = 0;
			int temp = -1;
			for (int j = 1; j < i; j++) {
				if(high[j]>=high[i]){
					if (dp[j]>=temp) {
						position=j;
						temp=dp[j];
					}
				}
			}
			dp[i]=dp[position]+1;
		}
		int max =0;
		for (int i = 1; i < dp.length; i++) {
			if (dp[i]>=max) {
				max=dp[i];
			}
		}
		System.out.println(max);
	}

}



  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obession

觉得有用可以打赏咖啡一杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值