动态规划 动态规划算法通常用于求解具有某种最优性质的问题。 动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。
83 爬楼梯的最少成本
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
每当爬上一个阶梯都要花费对应的体力值,一旦支付了相应的体力值,就可以选择向上爬一个阶梯或者爬两个阶梯。
请找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
https://leetcode-cn.com/problems/GzCJIP/https://leetcode-cn.com/problems/GzCJIP/
//构造公式最重要 dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2])
func minCostClimbingStairs(cost []int) int {
n := len(cost)
dp := make([]int, n+1)
for i := 2; i <= n; i++ {
dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2])
}
return dp[n]
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
84 房屋偷盗
一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组 nums ,请计算 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
func max(a, b int) int {
if a > b {
return a
}
return b
}
//定义 dp[i]为偷盗至i房间的最大收获值,初始可以选择从第一个房子偷还是第二个
//dp[0] = nums[0]
//dp[1] = nums[1]
//dp[2] = max(dp[1],dp[0]+nums[2])
//dp[i] = max(dp[i-1],dp[i-2]+nums[i])
func rob(nums []int) int {
if len(nums) < 2 {
//题目告诉我们nums长度一定大于等于1
return nums[0]
}
dp := make([]int, len(nums))
dp[0] = nums[0]
dp[1] = max(nums[0],nums[1])
for i := 2; i < len(nums); i++ {
dp[i] = max(dp[i-1], dp[i-2]+nums[i])
}
return dp[len(dp)-1]
}
85 环形房屋偷盗
一个专业的小偷,计划偷窃一个环形街道上沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组 nums ,请计算 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
func robNoCicle(nums []int) int {
if len(nums) < 2 {
//题目告诉我们nums长度一定大于等于1
return nums[0]
}
dp := make([]int, len(nums))
dp[0] = nums[0]
dp[1] = max(nums[0],nums[1])
for i := 2; i < len(nums); i++ {
dp[i] = max(dp[i-1], dp[i-2]+nums[i])
}
return dp[len(dp)-1]
}
//房子改成了环形的,选了0就不能选length-1
//两种情况,选0 0 -- nums[i-1]
//选 1 0-- nums[i]
func rob(nums []int) int {
if len(nums) < 2 {
//题目告诉我们nums长度一定大于等于1
return nums[0]
}
num1:=robNoCicle(nums[1:])
num2:=robNoCicle(nums[:len(nums)-1])
return max(num1,num2)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
86 粉刷房子
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。
请计算出粉刷完所有房子最少的花费成本。
func min(a, b int) int {
if a < b {
return a
}
return b
}
//红 蓝 绿
//00 0号红 01 0号蓝 02 0号绿
//dp[i][j] 表示到i房子选j花费最小值
//dp[i][0] = min(dp[i-1][1]+costs[i][0],dp[i-1][2]+costs[i][0])
//dp[i][1] = min(dp[i-1][0]+costs[i][1],dp[i-1][2]+costs[i][1])
//dp[i][2] = min(dp[i-1][0]+costs[i][2],dp[i-1][1]+costs[i][2])
func minCost(costs [][]int) int {
//转换cost
dp:=make([][]int,len(costs))
for i:=0;i<len(dp);i++{
dp[i] = make([]int,3)
}
dp[0] = costs[0]
for i:=1;i<len(costs);i++{
dp[i][0] = min(dp[i-1][1]+costs[i][0],dp[i-1][2]+costs[i][0])
dp[i][1] = min(dp[i-1][0]+costs[i][1],dp[i-1][2]+costs[i][1])
dp[i][2] = min(dp[i-1][0]+costs[i][2],dp[i-1][1]+costs[i][2])
}
//取最小
var res int
res = min(dp[len(costs)-1][0],dp[len(costs)-1][1])
res = min(res,dp[len(costs)-1][2])
return res
}