首页 > 其他分享 >代码随想录day37 || 518 零钱兑换,377 组合总和iv,70 爬楼梯

代码随想录day37 || 518 零钱兑换,377 组合总和iv,70 爬楼梯

时间:2024-08-22 11:30:23浏览次数:4  
标签:背包 组合 int day37 随想录 518 遍历 物品 dp

0-1 背包问题

  • 在 0-1 背包问题中,每种物品只能选择一次,因此一旦选择某个物品后,剩余的容量只能放入前面的物品。这就是为什么状态转移方程是:

dp[i][j] = max(dp[i-1][j], dp[i-1][j-w(i)] + v(i))
这里的 dp[i-1][j-w(i)] + v(i) 表示选择第 ( i ) 个物品后,剩余的容量只能放入前 ( i-1 ) 个物品。

// 如果是一维数组,0-1背包需要倒叙遍历保证每个物品只使用一次
for i:=0; i<len(物品); i++{
	for j:=len(背包)+1; j>=weight[i]; j--{
		dp[j] = max(dp[j], dp[j-weight[i]] + value(i))
	}
}

完全背包问题

  • 在完全背包问题中,每种物品可以重复放入多次,因此一旦选择某个物品后,剩余的容量仍然可以放入当前物品。这就是为什么状态转移方程是:

dp[i][j] = max(dp[i-1][j], dp[i][j-w(i)] + v(i))

这里的 dp[i][j-w(i)] + v(i) 表示选择第 ( i ) 个物品后,剩余的容量仍然可以放入第 ( i ) 个物品。

// 如果是一维数组,完全背包只需要变成正序遍历即可,因为每个物品都可以多次使用
// 先物品后背包,得出的是全组合,原因在于外层的物品是按照顺序便利的,所以 物品(2) 永远不会出现在物品(1) 前面
for i:=0; i<len(物品); i++{
	for j:=0; j<len(背包)+1; j++{
		dp[j] = max(dp[j], dp[j-weight[i]] + value(i))
	}
}

// 先背包后物品得出的是全排列 物品=[1,2,3]
// 对于每一个背包容量,dp[2] = (1,1) + (2) = 2 种方式
// 然后到dp[3], 遍历物品1 dp[3] = dp[3] + dp[3-1] = 0 + 2 = 2  (1,1,1) (2,1) ,其实此处就可以看出可以倒叙了
// 遍历物品2 dp[3] = dp[3] + dp[3-2] = 2 + 1 = 3  (1,1,1) (2,1) (1,2) !! 最后一个(1,2)代表的是dp[0]的排列(1) ,加上此时遍历到的物品2,==> (1,2)
// 遍历物品3 dp[3] = dp[3] + dp[3-3] = 3 + 1 = 4  (1,1,1) (2,1) (1,2) (3) !! 此处其实也可以解释为什么dp[0]=1, 因为如果物品重量恰好等于背包容量,就必须有一种方法装入
for j:=0; j<len(背包)+1; j++{
	for i:=0; i<len(物品); i++{
		dp[j] = max(dp[j], dp[j-weight[i]] + value(i))
	}
}

总结

  • 0-1 背包:每个物品只能选一次,状态转移依赖于前一个状态。
  • 完全背包:每个物品可以选多次,状态转移可以依赖于当前状态。

518 零钱找还

func change(amount int, coins []int) int {
	// 完全背包相比与0-1背包不同的是,每个物品可以取无限次,所以在遍历物品时,要从前往后遍历
	// dp五部曲
	// dp数组以及下标含义  dp[i][j] 表示使用前j个物品转容量为i的背包能装的数量组合
	// 递推公式 dp[i][j] = dp[i][j-w[i]] + dp[i-1][j] // 装i组合数量 + 不装i组合数量
	// 初始化,装满背包0有1种方法, dp[0][0] = 1
	// 遍历顺序,先物品后背包
	// print

	var dp = make([][]int, len(coins) + 1)
	for idx, _ := range dp {
		dp[idx] = make([]int, amount + 1)
	}

	dp[0][0] = 1

	for i:=0; i<len(coins); i++ {
		for j:=0; j<amount+1; j++{
			if j - coins[i] >= 0 {
				dp[i+1][j] = dp[i][j] + dp[i+1][j-coins[i]]
			}else {
				dp[i+1][j] = dp[i][j]
			}
		}
	}
	//fmt.Println(dp)
	return dp[len(coins)][amount]
}

组合总和iv

func combinationSum4(nums []int, target int) int {
	// 和零钱兑换解法一致, 多出来的一点在于需要判断不同的组合,由于二维数组不区分遍历顺序,所以只能使用先背包后物品的全排列
	// dp五部曲
	// dp数组以及下标含义  dp[j] 表示容量为j的背包能装满的数量排列
	// 递推公式 dp[j] = dp[j-w[i]] + dp[j] // 装i组合数量 + 不装i组合数量
	// 初始化,装满背包0有1种方法, dp[0] = 1
	// 遍历顺序,先背包后物品
	// print

	var dp = make([]int, target + 1)

	dp[0] = 1
	for j:=1; j<=target; j++ {
		for i:=0; i<len(nums); i++{
			if j - nums[i] >= 0 {
				dp[j] = dp[j] + dp[j-nums[i]]
			}
		}
	}
	//fmt.Println(dp)
	return dp[target]
}

70 爬楼梯

func climbStairs(n int) int {
	// 使用完全背包思路
	// dp[j]表示装满容量j的背包排列数
	// 递推 dp[j] = dp[j] + dp[j-w(j)]
	// dp[0] = 1
	// 遍历顺序 全排列完全背包 先正序背包 后正序物品
	// print

	var dp = make([]int, n+1)
	dp[0] = 1
	for j:=1; j<=n; j++ {
		for i:=0; i<=2; i++{
			if j>=i{
				dp[j] = dp[j] + dp[j-i]
			}
		}
	}
	fmt.Println(dp)
	return dp[n]
}

标签:背包,组合,int,day37,随想录,518,遍历,物品,dp
From: https://www.cnblogs.com/zhougongjin55/p/18373461

相关文章

  • 代码随想录Day22
    77.组合给定两个整数n和k,返回范围[1,n]中所有可能的k个数的组合。你可以按任何顺序返回答案。示例1:输入:n=4,k=2输出:[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],]示例2:输入:n=1,k=1输出:[[1]]提示:1<=n<=201<=k<=n正解......
  • 代码随想录day36 || 1049 最后一筐石头重量||, 494 目标和,474 一和零
    1049最后一块石头重量||funclastStoneWeightII(stones[]int)int{ //本题思路在于要想得到最小差,就要尽可能将石头分割为两堆相近的重量,然后转换为背包问题 //dp[i]表示容量i背包能装的石头总价值,其中重量和价值相等 //递推公式dp[j]=max(dp[j],dp[j-w(i)]+v[i]......
  • 「代码随想录算法训练营」第四十三天 | 图论 part1
    797.所有可能的路径题目链接:https://leetcode.cn/problems/all-paths-from-source-to-target/description/文章讲解:https://programmercarl.com/kamacoder/0098.所有可达路径.html题目难度:中等题目状态:看题解思路一:DFSvoiddfs(vector<vector<int>>&graph,intx,intn......
  • 代码随想录Day21
    669.修剪二叉搜索树给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low,high]中。修剪树不应该改变保留在树中的元素的相对结构(即,如果没有被移除,原有的父代子代关系都应当保留)。可以证明,存在唯一的答案。所......
  • 基于微信小程序的甜品销售系统的设计与实现-计算机毕业设计源码51887
    摘 要随着移动互联网的快速发展和智能手机的普及,外卖行业已成为人们日常生活中不可或缺的一部分。然而,传统的外卖方式存在操作繁琐、信息不准确等问题。为解决这些问题,本项目设计并实现了一款基于微信小程序的甜品销售系统。该系统通过微信小程序作为前端界面,结合后端技术......
  • 「代码随想录算法训练营」第四十二天 | 单调栈 part2
    42.接雨水题目链接:https://leetcode.cn/problems/trapping-rain-water/文章讲解:https://programmercarl.com/0042.接雨水.html题目难度:困难视频讲解:https://www.bilibili.com/video/BV1uD4y1u75P/题目状态:这道题目在LeetCodeTop100中做过,使用两种方法,再回顾一下思路一:单......
  • 代码随想录day35 || 416 分割等和子集
    背包问题有n件物品和一个最多能背重量为w的背包。第i件物品的重量是weight[i],得到的价值是value[i]。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。//pake//// @Description:// @paramweights:物品i对应重量// @paramvalue:物品i对应价值// @......
  • 「代码随想录算法训练营」第四十一天 | 单调栈 part1
    739.每日温度题目链接:https://leetcode.cn/problems/daily-temperatures/文章讲解:https://programmercarl.com/0739.每日温度.html题目难度:中等视频讲解:https://www.bilibili.com/video/BV1my4y1Z7jj/题目状态:看题解思路:定义一个单调栈,该栈存放下标,规则是要保持其下标对......
  • 代码随想录day34 || 62 不同路径,63 不同路径||,343整数拆分,96 不同搜索二叉树
    不同路径funcuniquePaths(mint,nint)int{ //dp五部曲 //dp数组以及下标的含义dp[i][j]代表从0,0走到i,j的不同路径条数 //递推公式 dp[i][j]=dp[i-1][j]+dp[i][j-1] //dp数组的初始化dp[i][0]==dp[0][j]=1 //遍历顺序 外层按照行,内层按照列遍历......
  • 代码随想录Day18
    530.二叉搜索树的最小绝对差给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。示例1:输入:root=[4,2,6,1,3]输出:1示例2:输入:root=[1,0,48,null,null,12,49]输出:1提示:树中节点的数目范围是......