• 0-1背包问题


    问题:

    有N件物品和一个容量为V的背包。第i件物品的价值是c[i],重量是w[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

    这个问题的特点是:每种物品只有一件,可以选择放或者不放。用f[i][j]表示背包当前容量为j,选择装入1-i个物品时的最大价值

    在求最优解的背包问题中,一般有两种不同的问法:1、求小于等于背包容量的最优解,即不一定恰好装满背包;2、要求“恰好装满背包”时的最优解.

    1、求小于等于背包容量的最优解,即不一定恰好装满背包;

    设f[0..N][0..v]=0

    2、要求“恰好装满背包”时的最优解.

    则f[0][1..v]=-∞,确保当背包不满时得不到最优解(价值最大)

    状态转移方程:

    1. f[i][j]=f[i-1][j]         j<w[i-1]
    2. f[i][j]=max{f[i-1][j].f[i-1][j-w[i-1]]+c[i-1]}        其它

    解释:

    1.背包当前容量j小于第i件物品的重量w[i-1],第i件物品装不下,所有不放第i件物品

    2.第i件物品可以放下,进行选择,放或者不放

    • 如果不放,则问题转化为“前i-1件物品放入容量为j的背包中”
    • 如果放,则问题转化为“前i-1件物品放入剩下的容量为j-w[i-1]的背包中”,此时能获得的最大的价值就是f[i-1][j-w[i-1]]再加上通过放入第i件物品获得的价值c[i-1]

    在“其它”情况下,f[i][j]的值就是上述两种情况中的最大值

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int f[100][100];
     4 int Min=-999999;
     5 int package(int n,int v,int w[],int c[])    //n-物品数量,v-背包容量,w[]各个物品的重量,c[]对应物品的价值
     6 {
     7     if(f[n][v]!=0)                    //已计算过该子问题
     8         return f[n][v];
     9     if(n==0||v<=0)      //题型一:价值最大,不要求装满
    10         return 0;
    11 
    12     //if(n==0)    //题型二:背包装满的情况下最大价值,设f[0][0]=0,f[0][1..v]=-∞,即当背包不满时没有最优解
    13     //{
    14     //    if(v!=0) return Min;
    15     //    return 0;
    16     //}
    17 
    18     if(v<w[n-1])           //第n件物品的重量大于当前背包的容量,则不装第n件物品,背包容量仍为v,从剩余的n-1件物品中选择
    19         f[n][v]=package(n-1,v,w,c);
    20     else               //背包当前容量可以装下第n件物品,可以选择装或者不装第n件物品
    21     {
    22         int a=package(n-1,v,w,c);      //不装第n件物品,从剩余的n-1件物品中选择,背包容量仍为v
    23         int b=package(n-1,v-w[n-1],w,c)+c[n-1];   //装第n件物品,则当前价值为第n件物品的价值c[n]加上(n-1,v-w[n])问题的最优解
    24         f[n][v]=a>b?a:b;            //选择价值最大的解
    25     }
    26     return f[n][v];
    27 }
    28 
    29 int main()
    30 {
    31     memset(f,0,sizeof(f));    //设置边界条件
    32     int n,v,w[100],c[100];
    33     cout<<"input the number of items:";
    34     cin>>n;
    35     cout<<"input the volume of items:";
    36     cin>>v;
    37     cout<<"input the weight of items:";
    38     for(int i=0;i<n;i++)
    39         cin>>w[i];
    40     cout<<"input the value of items:";
    41     for(int i=0;i<n;i++)
    42         cin>>c[i];
    43     cout<<"the bigest value is:";
    44     cout<<package(n,v,w,c)<<endl;
    45 }
    View Code

    结果:

    问法一:求小于等于背包容量的最优解,即不一定恰好装满背包;

    问法二:要求“恰好装满背包”时的最优解.

  • 相关阅读:
    [Android Training视频系列]2.3 Stopping and Restarting an Activity
    [Android Training视频系列]2.1 Starting an Activity
    【Android每日一讲】2012.11.29 自定义下拉菜单模式 Spinner与setDropDownViewResource
    【Android每日一讲】2012.11.28 快速地搜索手机文件引擎 Java IO的应用
    [Android Samples视频系列之ApiDemos] AppActivityTranslucent
    [Android Samples视频系列之ApiDemos] AppActivityTranslucentBlur和Wallpaper
    [Android Training视频系列]2.2 Pausing and Resuming an Activity
    [Android Training视频系列]1.4 Starting Another Activity
    [Android Samples视频系列之ApiDemos] AppActivitySaveRestore State
    [Android Samples视频系列之ApiDemos] AppActivitySetWallpaper
  • 原文地址:https://www.cnblogs.com/mrlsx/p/5466861.html
Copyright © 2020-2023  润新知