动态规划(2)

01背包问题(中篇)

01背包问题 最优解的回溯(back

那么通过上一回合的分析,我们知道了,二维数组的dp[amount][capacity]的value就是我们想要的最大背包价值。光是知道这么value是不够的,我们还行知道它是由哪些编号的物品组成的,how to solve this issue 呢。首先,我们就得对这dp图的存储理清楚,dp[i][j]这个空里的value是怎么得来的:如果if w[i](放入的物品重量)>j(当前设定的背包容量),那么 此时的dp[i][j] = dp[i-1][j]说明dp[i][j] 与上面dp[i-1][j]的值一样,这个物品i没有放进去。,如果j < w[i],dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]); 换句话说,要是dp[i][j]!=dp[i-1][j],就说明物品i放进背包中了。好,我们知道了dp[amount][capacity]的location了,是不是就可以开始递归回溯(back)了呢?这回溯的过程中,再判断dp[i][j]是否等于dp[i-1][j],来对i进行标记了。key point:如果当前的i的确放入了背包中,那么 我们就应该回溯到dp[i-1][j-w[i]] 这个位置
在这里插入图片描述

// 01 Backpack Problem
//i(物品编号)	1	2	3	4
//w(体积)	    2	3	4	5
//v(价值)	    3	4	5	6
#include<iostream>
using namespace std;
const int N=15;
const int amount = 4;
const int capacity = 8; 
int w[5] = {0,2,3,4,5};
int v[5] = {0,3,4,5,6};
int dp[N][N] = {{0}};
int temp[amount+1]={0};
void theBack(int i, int j) {				
	if (i >= 0) {
		if (dp[i][j]==dp[i-1][j]) {     //说明当前的物品i并没有在最优解中,向上退一步,继续回溯 。 
			temp[i] = 0;
			theBack(i - 1, j);
		}
		else if (j-w[i] >= 0 &&dp[i][j] == dp[i-1][j-w[i]]+v[i]) {   //将物品i记录在temp中,并跳转至添加物品前的上一个最优解位置 
			temp[i] = 1;
			theBack(i-1, j-w[i]);
		}
	}
}
int main(){
  
   for(int i =1;i<5; i++ ){
   	for(int j = 1; j < capacity+1;j++){
   		if(j < w[i])
   		    dp[i][j] = dp[i-1][j];
   		else{
   			dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
   		} 	  
   	}
   }
   for (int i=0; i <5; i++) {
   	for (int j=0; j < capacity+1; j++) {
   		cout << dp[i][j] << ' ';
   	}
   	cout << endl;
   }
   cout<<dp[amount][capacity];
   theBack(amount,capacity);
   cout<<endl<<"The optimal solution is:";
   for (int i=0; i < amount+1; i++){		
	  if(temp[i]!=0)
	  cout<<i<<" ";
}
   return 0;
}

解决完最优解问题后,我们再思考思考,这是个二维数组,数组空间中还有很大一部分data不是我们想要的(或是意义不大的),那一维数组能够实现数据的动态存储吗…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值