动态规划(背包问题-golang)

【0-1背包问题】
问题描述:

有n个物品和一个最多能承受重量为 W 的背包,其中第 i 件物品的重量是weight [ i ] ,所对应的价值为value[i],每一件物品只有一件(即只能放入背包一次),求解将哪些物品放入背包后得到的背包中物品的总价值最大?
递归分析
weight物品的重量,那么我们从0开始选择,就存在选或者不选的两种情况,在这两种情况之下,那么背包的重量也存在两种情况,可以装下或者无法装下,递归函数如下:
// weight 物品的容量
// value 物品的价值
// index 当前开始选择物品的索引
// bag 背包的剩余容量
func process(weight,value []int,index,bag int) int{
	// 背包容量没有剩余
	// 严格小于0
	if bag < 0 {
		return -1
	}
	// 到达最后一个货物
	if index = len(weight) {
		return 0
	}
	// 不选择当前货物
	p1 := process(weight,value,index+1,bag)
	p2 := 0
	// 选择当前货物,则bag会减少,并且需要判断选择当前货物之后容量是否还需要继续选择
	next := process(weight,value,index,bag-weight[indx])
	if next != -1{
		p2 = value[index] + next
	}
	// 返回最大值
	if p1 > p2 {
		return p1
	}
	return p2
}

动态规划
动态规划实际上是将递归过程中产生的重复的值进行缓存,然后后续在使用重复值的时候直接选择。
// weight 物品的容量
// value 物品的价值
// index 当前开始选择物品的索引
// bag 背包的剩余rongliang
func dp(weight, value []int, bag int) int {
	m := len(weight)
	// 首先该方法中weight,value是常量,所以动态规划表中不用考虑
	dp := make([][]int, m+1)
	// 所有值初始化为0
	for i := 0; i < m+1; i++ {
		dp[i] = make([]int, bag+1)
	}
	for index := m - 1; index >= 0; index-- {
		for rest := 0; rest <= bag; rest++ {
			// p1 := process(w, v, index+1, bag)
			p1 := dp[index+1][rest]
			p2 := 0
			next := 0
			// 选择当前物品,背包容量减小,背包容量合法性
			if rest - weight[index] >= 0  {
				p2 = value[index] + dp[index+1][rest-weight[index]]
			}
			// 选择最大价值
			if p1 > p2 {
				dp[index][rest] = p1
			} else {
				dp[index][rest] = p2
			}
		}
	}
	return dp[0][bag]
}

Go 语言中的背包问题(Knapsack Problem)通常是指动态规划算法的一个应用实例,它涉及到在给定容量限制下选择物品以获得最大的价值。在 Go 中解决背包问题,你需要定义一个二维数组或矩阵,其中每个元素 `(i, j)` 表示前 i 个物品中有价值 j 的物品可以选择。常见的解决方案包括: 1. 动态规划:通过填充值表 `dp[i][j]`,计算包含前 i 个物品且总重量不超过 j 时的最大价值。初始条件通常是 `dp[0][j] = 0` 和 `dp[i][0]` 等于不包含第 i 个物品的价值。 ```go func knapSack(W int, wt []int, val []int, n int) int { dp := make([][]int, n+1) for i := range dp { dp[i] = make([]int, W+1) } for i := 1; i <= n; i++ { for w := 1; w <= W; w++ { if wt[i-1] <= w { dp[i][w] = max(dp[i-1][w], dp[i-1][w-wt[i-1]] + val[i-1]) } else { dp[i][w] = dp[i-1][w] } } } return dp[n][W] } // 定义辅助函数 max(a, b) func max(a, b int) int { if a > b { return a } return b } ``` 2. 回溯法:这是一种递归解法,从最大值开始尝试添加物品,直到达到容量限制。 ```go func backtracking(W int, wt []int, val []int, n int, currWeight int, dp [][]bool) bool { if currWeight == W || n == 0 { dp[n][currWeight] = true return dp[n][currWeight] } dp[n][currWeight] = dp[n-1][currWeight] if wt[n-1] <= currWeight { dp[n][currWeight] |= backtracking(W, wt, val, n-1, currWeight-wt[n-1], dp) } return dp[n][currWeight] } // 初始化dp数组 var dp [][2]int = make([][]bool, n+1) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值