/*
01 背包问题:
有一个容量为 V 的背包,有 N 件物品,
第 i 件物品的体积是 C[i],
第 i 件物品的价值是 W[i],
求解如何装载可以使得价值最大。
基本思路:
这是最基础的背包问题,
特点是:每种物品仅有一件,
可以选择放或不放。
用子问题定义状态:
即 f[i][v] 表示前 i 件物品恰放入一个容量为 v 的背包可以获得的最大价值。
则其状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
如果不放第 i 件物品,那么问题就转化为 “ 前 i-1 件物品放入容量为 v 的背包中 ” ,
价值为 f[i-1][v] ;
如果放第 i 件物品,那么问题就转化为 “ 前 i-1 件物品放入剩下的容量为 v-c[i] 的背包中 ” ,
此时能获得的最大价值就是 f[i-1][v-c[i]] 再加上通过放入第 i 件物品获得的价值 w[i]
[Test]
public void Testdp01Package()
{
_01PackageDp dp=new _01PackageDp();
dp.Calculate();
}
*/
using System ;
namespace dp
{
/// <summary>
/// Description of _01PackageDp.
/// </summary>
public class _01PackageDp
{
//use an array to define volumn for each package
private int [] C = new int [ 5 ]{ 5 , 15 , 20 , 10 , 2 };
//use an array to define value for each package
private double [] W = new double [ 5 ]{ 15 , 44 , 65 , 25 , 5 };
//use an array with 2 dimension to remember passed calculate result
private double [,] opt = new double [ 6 , 31 ];
public double Calculate ()
{
for ( int i = 0 ; i <= 5 ; i ++)
for ( int j = 0 ; j <= 30 ; j ++)
{
if ( i == 0 || j == 0 )
opt [ i , j ]= 0 ;
else
opt [ i , j ]= Int16 . MinValue ;
}
double finalResult = GetOpt ( 5 , 30 );
return finalResult ;
}
double GetOpt ( int Number , int Voulmn )
{
//using a array to store passed result can reduce times of recursion
if ( opt [ Number , Voulmn ]!= Int16 . MinValue )
return opt [ Number , Voulmn ];
//without opt array can code like follow, every time recursion from 0
//if(Number==0||Voulmn==0)
//return 0;
double PutNumberI = 0 ;
double notPutNumberI = 0 ;
notPutNumberI = GetOpt ( Number - 1 , Voulmn );
if ( Voulmn < C [ Number - 1 ]) //the left volumn not enough for number i stuff
return notPutNumberI ;
else
PutNumberI = GetOpt ( Number - 1 , Voulmn - C [ Number - 1 ])+ W [ Number - 1 ];
double result = Max ( notPutNumberI , PutNumberI );
opt [ Number , Voulmn ]= result ;
return result ;
}
double Max ( double a , double b )
{
return a >= b ? a:b ;
}
}
}