动态规划问题一:背包问题

学习自:Christal_R

有一个背包,能盛放的物品总重量为capacity,设有number件物品,其重量分别为w1,w2,…,wn,希看从N件物品中选择若干物品,所选物品的重量之和恰能放进该背包,即所选物品的重量之和即是S。
在这里插入图片描述
寻找递推关系式,面对当前商品有两种可能性:
第一,包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);

第二,还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) },其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i);

由此可以得出递推关系式:

  1. j<w(i) V(i,j)=V(i-1,j)
  2. j>=w(i) V(i,j)=max{ V(i-1,j),V(i-1,j-w(i))+v(i) }
void FindMax()//动态规划
{
    int i,j;
    //填表
    for(i=1;i<=number;i++)
    {
        for(j=1;j<=capacity;j++)
        {
            if(j<w[i])//包装不进
            {
                V[i][j]=V[i-1][j];
            }
            else//能装
            {
                if(V[i-1][j]>V[i-1][j-w[i]]+v[i])//不装价值大
                {
                    V[i][j]=V[i-1][j];
                }
                else//前i-1个物品的最优解与第i个物品的价值之和更大
                {
                    V[i][j]=V[i-1][j-w[i]]+v[i];
                }
            }
        }
    }
}

表格填完,最优解即是V(number,capacity)=V(4,8)=10,但还不知道解由哪些商品组成,故要根据最优解回溯找出解的组成,根据填表的原理可以有如下的寻解方式:

  1. V(i,j)=V(i-1,j)时,说明没有选择第i 个商品,则回到V(i-1,j);
  2. V(i,j)=V(i-1,j-w(i))+v(i)实时,说明装了第i个商品,该商品是最优解组成一部分,随后我们得回到装该商品之前,即回到V(i-1,j-w(i));
  3. 一直遍历到i=0结束为止,所有解的组成都会找到。
void FindWhat(int i,int j)//寻找解的组成方式
{
    if(i>=0)
    {
        if(V[i][j]==V[i-1][j])//相等说明没装
        {
            item[i]=0;//全局变量,标记未被选中
            FindWhat(i-1,j);
        }
        else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
        {
            item[i]=1;//标记已被选中
            FindWhat(i-1,j-w[i]);//回到装包之前的位置
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42034217/article/details/84640553
今日推荐