zoukankan      html  css  js  c++  java
  • 动态规划---爬楼梯和硬币组合问题

    爬楼梯

    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
    每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
    注意:给定 n 是一个正整数。

    输入: 3  
    输出: 3
    解释: 有三种方法可以爬到楼顶。
    1.  1 阶 + 1 阶 + 1 阶
    2.  1 阶 + 2 阶
    3.  2 阶 + 1 阶
    

    不难发现,对于要抵达的第n阶台阶,有两种方式可以抵达。

    1. 在第 (i−1) 阶后向上爬 1 阶。
    2. 在第 (i-2) 阶后向上爬 2 阶。
      得出状态转移方程为
    dp[i]=dp[i−1]+dp[i−2]
    

    因此可以得出代码如下:

    func climbStairs(n int) int {
    	if n <= 1 {
    		return n
    	}
    	dp := make([]int, n+1)
    	dp[1] = 1
    	dp[2] = 2
    	for i := 3; i <= n; i++ {
    		dp[i] = dp[i-1] + dp[i-2]
    	}
    	return dp[n]
    }
    

    拓展:如果每次我可以爬 1 或 3 或 5 个台阶,这时候有多少种方式可以抵达呢?
    原理和每次迈1或2步的时候是一样的,我们就在内部循环可以迈的台阶,进行计算有多少种抵达方式。代码如下:

    func climbStairs(n int) int {
    	if n <= 1 {
    		return n
    	}
    	dp := make([]int, n+1)
    	step := []int{1, 3, 5}
    	dp[0] = 1
    	for i := 1; i <= n; i++ {
    		for j := 0; j < len(step); j++ {
    			if i >= step[j] {
    				dp[i] += dp[i-step[j]]
    			}
    		}
    	}
    	return dp[n]
    }
    

    硬币组合问题

    给定数量不限的硬币,币值为25分、10分、5分和1分,编写代码计算n分有几种表示法。

     输入: n = 10
     输出:4
     解释: 有四种方式可以凑成总金额:
     10=10
     10=5+5
     10=5+1+1+1+1+1
     10=1+1+1+1+1+1+1+1+1+1
    

    仔细思考一下,硬币组合问题和爬楼梯问题其实是极其相似的。比如对于给定n = 6的情况下,我们可以从两种情况抵达:

    1. 从 n = 5 的情况下加一个1分硬币
    2. 在 n = 1 的情况下加一个5分硬币

    乍一看,代码完全应该和上面是一样的嘛!但是如果直接使用上面的代码去计算,会发现最后得出的结果比预料的要多。可以尝试下运行爬楼梯拓展中的代码,计算n=6的情况。为什么?

    还是以 n = 6 的情况进行举例
    在爬楼梯问题中,先上1步再上5步([1,5]) 和 先上5步再上1步([5,1]) 是2个不同的情况。
    在硬币组合问题中,[1,5] 和 [5,1]属于同一个解决方案,都只是使用了一个1分硬币一个5分硬币。
    即硬币组合问题中,硬币的排列顺序不会产生不同的解决方案

    那么如何避免硬币的顺序对结果造成的影响呢?答案就是:调换遍历顺序,先遍历硬币,保证在考虑一种硬币的时候没有其它大面额硬币的影响,保证解决方案中始终是小硬币在前大硬币在后。避免重复计算问题,同样在n=6的情况下,解决方案计算只有[1,1,1,1,1,1]和[1,5] 两种。
    代码:

    func waysToChange(n int) int {
    	if n <= 1 {
    		return n
    	}
    	dp := make([]int, n+1)
    	coin := []int{1, 5, 10}
    	dp[0] = 1
    	for i := 0; i < len(coin); i++ {
    		for j := 1; j <= n; j++ {
    			if j >= coin[i] {
    				dp[j] += dp[j-coin[i]]
    			}
    		}
    	}
    	return dp[n]
    }
    
  • 相关阅读:
    FlashInspector 【Firefox浏览器插件,flash分析工具】
    屌丝和木耳
    Flash剪贴板功能
    sql newid()随机函数
    SQL 视图
    向SQL Server 现有表中添加新列并添加描述.
    sql server 约束 查找
    创建与删除SQL约束或字段约束
    SQLServer
    利用排序规则特点计算汉字笔划和取得拼音首字母
  • 原文地址:https://www.cnblogs.com/cplemom/p/12773632.html
Copyright © 2011-2022 走看看