/*
01背包动态规划思维不同于常规思维,
掌握方法及参数的内容,
动态转移方程的理解熟。
通过实例学习,
序号(i)|单个物体重量w(i)|单个物品价值v(i)
1 22 15
2 18 18
3 9 10
4 24 13
5 15 20
包能承最大重35
求total(5,35)的最大价值。
total(5,35)=total(4,35),不选第5个物品
total(5,35)=total(4,20)+v5,选时
(
1,怎樣理解 total( i,j)?
我們把它看成函數,它的值就是从i个物品中选,
總重量不超j的所选物品的最大价值。
i參數 是從前 i 個物品選,其中不一定遷中。
j參數是此時背包能承的最大重量。
如果选了一個物品 i,則剩下的空間承重為 j-W( i)
以下直观理解
A:从顶端开始,如 total( 5,35),
不选第5个物品,背包能承重仍然为35,
作為左子树
total( 4,35)。
B: 遷第5個物品時,
此時背包還能承的重量為(35-15),
剩下的物品在不包含第5個物品中遷。
此時函 数轉化為total(4,20)作為右子樹。
以下抽象扩展化
重復A,B后,得此題的樹,最后底層函數值全為0。
這其實是一遞歸過程,完成后再從底往上計算,
每個父結點的值為:(右子樹值加上父結點第I個物品價值,
與左子樹比較,哪個大就作為該父結點的值。
此反復可很方便得出頂根結點的值
total(5,35)=38。
把A,B抽象 ***total(i,j)*** 根
total(i-1,j)左子树; total(i-1 , j-w(i))+V(i)
以上就是背包問題的狀態轉移方程理解過程。
*/
#include <stdio.h>
int w[5]={22,18,9,24,15};
int v[5]={15,18,10,13,20};
int total(int i,int j){
int l,r,t;
if(i==-1||j==0)
return 0;
if(w[i]>j )
return total(i-1,j);
if(w[i]<=j ) {
l=total(i-1,j);
r=v[i]+total(i-1,j-w[i]);
t=l>r?l:r;
}
return t;
}
int main(){
printf("total(5,35)=%d\n",total(5,35));
return 0;
}