背包问题

背包问题

博主第一次写博客,不喜勿喷

0-1背包

0-1背包问题新建的dp表可以是一维或二维,二维对于小白来说会比较好理解,而一维的为了节省掉一点空间,就相对应的会提高理解的难度。
m[i],v[i]分别表示重量和价值,N, M分别表示物品数量和重量
首先上二维的代码

static void maxDp() {		
		for(int i = 0; i < N; i++) {
			for(int j = M; j >=m[i]; j--) {
				//用到i+1是因为我的m[i]和v[i]是从下标为0开始读入数据的
				dp[i+1][j] = Math.max(dp[i][j], dp[i][j-m[i]]+v[i]);		
			}
			
		}
		System.out.println(dp[N][M]);
	}

二维dp十分好理解,用i 与 i+1来区分状态。
看过很多博客都说0-1背包第二个for循环就要逆序写,完全背包就顺序写。。。其实换成二维的时候0-1背包第二个for循环顺序写也是没问题的- -|| 这其实是理解两个背包问题不同的最重要的地方了

然后再上一维dp的代码

static void maxDp1() {		
		for(int i = 0; i < N; i++) {
			for(int j = M; j >=m[i]; j--) {
				dp1[j] = Math.max(dp1[j], dp1[j-m[i]]+v[i]);
			}
			
		}
		System.out.println(dp1[M]);
	}

完全背包

接着是完全背包的代码

static void maxDp2() {		
		for(int i = 0; i < N; i++) {
			for(int j = m[i]; j <= M; j++) {
				dp2[j] = Math.max(dp2[j], dp2[j-m[i]]+v[i]);
			}
		}
		System.out.println(dp2[M]);
	}

然后实际代码就只有一行的区别。。实际上为什么0-1背包要逆序呢。。首先要理解 i是表示第i个物品的意思 因为逆序的状态转移的过程不会影响前者,而反过来完全背包恰恰就需要前者影响后者(前者影响后者就表示该物品被多次放入背包,后者不受前者影响就表示物品只能一次放入背包)

多重背包

然后关于多重背包,多重背包就是多了个参数k,k表示物品最多可以放入的数量。。可以用个很笨的方法多引入一个k然后再跑一次循环的状态转移= =这是我一开始想到的。
然鹅,,实际上把每个参数k的物品都看成是一种新的物品就好了。。
例如:k = 3, m[i] = 2, v[i] = 4;
就看成多了两种物品,一种是m[i] = 4, v[i] = 8,另一种是m[i] = 6, v[i] = 12;
然后再看成是0-1背包问题来解就好了。。

然后附上转换方式

		int len = N;
		for(int i = 0; i < len; i++) {
			for(int j = 2; j <= k[i]; j++) {
				m[N] = m[i]*j;
				v[N] = v[i]*j;
				N++;
			}
		}

剩下的换成0-1背包来做的代码就不加附上了。。


只附上了理解性代码,仅为了引发思考,不喜勿喷

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值