算法 01背包问题

package bagProblem

import "fmt"

func BagProblem1(weight, value []int, bagweight int) int {
	// 定义一个dp[i][j],表示将任意0-i物品放入包后,在包j重量时,包中的价值最大
	// 初始化dp都为0
	dp := make([][]int, len(weight))
	for i := 0; i < len(weight); i++ {
		// 这里为bagweight+1,表示重量从0开始到bagweight
		dp[i] = make([]int, bagweight+1)
	}

	// 初始化0号物品
	for j := 0; j <= bagweight; j++ {
		// 表示包能放下0号商品
		if weight[0] <= j {
			dp[0][j] = value[0]
		}
	}

	// 第i个商品放入j重量的包时,会有两种情况
	// 放入i的商品后,总重量超过了j,则此时包中的价值和放入i前相同 即 dp[i-1][j]
	// 放入i的商品后,总重量没超过j,此时包中的价值为 dp[i-1][j-weight[i]]+value[i]
	// 其中dp[i-1][j-weight[i]]代表没放入i时的最大价值
	// 状态转移方程为
	// dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i])

	for i := 1; i < len(weight); i++ {
		for j := 1; j <= bagweight; j++ {
			if weight[i] > j {
				dp[i][j] = dp[i-1][j]
			} else {
				dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i])
			}
		}
	}

	return dp[len(weight)-1][bagweight]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

// 压缩成一维数组
func BagProblem2(weight, value []int, bagweight int) int {
	// 定义一个dp[j],在包j重量时,包中的最大价值
	// 初始化dp都为0
	dp := make([]int, bagweight+1)

	// 第i个商品放入j重量的包时,会有两种情况
	// 不放物品i,则此时包中的价值和放入i前相同 即 dp[j]
	// 放入物品i,此时包中的价值为 dp[j-weight[i]]+value[i]、
	// 状态转移方程为
	// dp[j] = max(dp[j], dp[j-weight[i]]+value[i])

	// 不能先遍历重量,再遍历商品
	// 商品0的重量为1
	// 例如求dp[4]时,j=4,i=0,需要由max(dp[4], dp[4 - weight[0]] + value[0]),即max(dp[4],dp[3] +value[0])
	// 如果先遍历重量后遍历商品时会发现,dp[3]永远为0,说明每次都只取一个商品(因为dp[3]为初始化值,表示没有取过商品,进而表示每次只取一个商品)
	for i := 0; i < len(weight); i++ {
		for j := bagweight; j >= 0; j-- {
			fmt.Println(i)
			if j < weight[i] {
				dp[j] = dp[j]
			} else {
				dp[j] = max(dp[j], dp[j-weight[i]]+value[i])
			}
			fmt.Println(dp)

		}
	}

	return dp[bagweight]
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值