第五章实验报告
1. 实践题目
7-1 01背包问题
2. 问题描述
给定n(n<=100)种物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为C(C<=1000)。问:应如何选择装入背包中的物品,使得装入背包中物品的总价值最大? 在选择装入背包的物品时,对每种物品i只有两个选择:装入或不装入。不能将物品i装入多次,也不能只装入部分物品i。
3. 算法描述(包括解空间,画出测试样例的解空间树,剪枝(约束函数或限界函数)方法描述)
(1)解空间:对于变量n其解空间为(0/1,0/1,......)共n个0/1的组合所构成。
(2)解空间树:
(3)剪枝函数:
有两个:第一个针对左树的剪枝,即1的剪枝:其通过判断当前已经累积的重量加上当前a[i]的重量是否会超出背包容量,如果超出则剪枝。
第二个针对右树的剪枝,即0的剪枝:其通过估算接下来背包容量所能装入的最大价值来判断是否能超出前面已算出来的价值最大值,如果不能就剪枝。
#include<iostream> #include<algorithm> using namespace std; struct bag{ int value; int weight; }; int n; int cvalue; int cweight; int maxvalue; int maxweight; bag bags[101]; bool compare(bag bag1,bag bag2) { return bag1.value*bag2.weight>bag2.value*bag1.weight; } void dps(int i) { int uppervalue(int i); if(i>n) { if(cvalue>maxvalue) maxvalue=cvalue; return ; } if(bags[i].weight+cweight<=maxweight) { cweight+=bags[i].weight; cvalue+=bags[i].value; dps(i+1); cweight-=bags[i].weight; cvalue-=bags[i].value; } if(uppervalue(i+1)>maxvalue) dps(i+1); } int uppervalue(int i) { int leftweight=maxweight-cweight; int uppervalue=cvalue; if(i<=n) uppervalue+=(bags[i].value*leftweight)/bags[i].weight; return uppervalue; } int main(void) { cin>>n; cin>>maxweight; cvalue=0; cweight=0; maxvalue=0; for(int i=1;i<=n;i++) cin>>bags[i].weight>>bags[i].value; sort(bags+1,bags+n+1,compare); dps(1); cout<<maxvalue; return 0; }
4.心得体会
01背包问题是非常经典的问题,很多其他类似的问题都可以转换为特殊的01背包问题来讨论。要深刻地去理解其回溯解法的思想,并且注意是如何找出判断条件来进行剪枝的,如果剪枝的不好很可能就超时。