程序碎片-01背包递归

/*

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 ;

       }

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值