zoukankan      html  css  js  c++  java
  • 0-1背包的递归与非递归实现

     1/*0-1背包递归*/
    2#include<iostream> 2 #include <iomanip> 3 using namespace std; 4 5 int w[]={1,3,4,5};//物品重量数组 6 int v[]={2,30,44,20};//物品价值数组 7 int contain=5;//背包容量 8 int y[4]={-1,-1,-1,-1};//解向量,y[i]=1表示选取物品,y[i]=0表示不选取物品 9 10 int f(int n,int contain) 11 { 12 if(n==0 || contain==0){//当物品数量为0,或者背包容量为0时,最优解为0 13 return 0; 14 } 15 else 16 { 17 //从当前所剩物品的最后一个物品开始向前,逐个判断是否要添加到背包中 18 for(int i=n-1;i>=0;i--){ 19 //如果当前要判断的物品重量大于背包当前所剩的容量,那么就不选择这个物 20 //在这种情况的最优解为f(n-1,C) 21 if(w[i]>contain){ 22 y[i]=0; 23 return f(n-1,contain); 24 } 25 else 26 { 27 //如果当前待判断的物品重量wi<C,那么就选取f(n-1,C)和vi+f(n-1,C-wi)中的最大值 28 int tmp1=f(n-1,contain);//不选择物品i的情况下的最优解 29 int tmp2=v[i]+f(n-1,contain-w[i]);//选择物品i的情况下的最优解 30 //返回选择物品i和不选择物品i中最优解大的一个 31 if(tmp1>tmp2){ 32 y[i]=0;//这种情况下表示物品i未被选取 33 return tmp1; 34 } 35 else 36 { 37 y[i]=1;//物品i被选取 38 return tmp2; 39 } 40 } 41 } 42 } 43 } 44 int main() 45 { 46 int maxvalue=f(4,5); 47 for(int i=0;i<4;i++){ 48 if(y[i]==1) 49 { 50 cout<<"Object"<<i+1<<"is selected"<<"It's value is"<<setw(2)<< 51 v[i]<<"It's Weight is"<<setw(2)<<w[i]<<endl; 52 } 53 } 54 cout<<"Maximum Value is"<<maxvalue<<endl; 55 return 0; 56 57 }
     1 /* 0-1背包非递归*/
     2 #include "stdio.h"
     3 #define N 100
     4 
     5 int main()
     6 {
     7     void Knapsack(int [],int [],int ,int ,int [][1000]);
     8     void Traceback(int [],int [],int ,int ,int [][1000],int []);
     9     int n,i,c,v[N+1],w[N+1],m[N+1][1000],x[N+1];
    10     //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
    11     //m[][]:存放最大总价值的数组
    12     //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
    13     //x[i]表示是否放入第i件物品,1为是,0为否
    14     printf("input n:");
    15     scanf("%d",&n);
    16     printf("input c:");
    17     scanf("%d",&c);
    18     printf("input v:");
    19     for(i=1;i<=n;i++) scanf("%d",&v[i]);
    20     printf("input w:");
    21     for(i=1;i<=n;i++) scanf("%d",&w[i]);
    22     Knapsack(v,w,c,n,m);
    23     Traceback(v,w,c,n,m,x);
    24     printf("answer:%d
    ",m[1][c]);
    25     for(i=1;i<=n;i++)
    26       if(x[i]) printf("%d ",i);
    27     printf("
    ");
    28     
    29     return 0;
    30 }
    31 
    32 void Knapsack(int v[],int w[],int c,int n,int m[][1000])
    33 //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
    34 //m[][]:存放最大总价值的数组
    35 //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
    36 {
    37     int i,j,t;
    38     int jMax; 
    39     jMax=w[n]-1<=c? w[n]-1:c;
    40     //jMax是使m[n][x]为0的x最后下标
    41     for(j=0;j<=jMax;j++) m[n][j]=0;
    42     //对于背包容量k(0<=k<=jMax),物品n是超重的,故在这些容量下,一定不会选择物品n
    43     //故(m[n][0],m[n][1],...m[n][jMax-1],m[n][jMax]) = 0
    44     for(j=w[n];j<=c;j++) m[n][j]=v[n];
    45     //对于背包容量k(w[n]<=k<=c),物品n是可容纳的,故在这些容量下,选择物品n
    46     //以下是前面两个for循环的实例:
    47     //例1:n=6,w[6]=9,c=12,则(m[6][0],m[6][1],m[6][2],...m[6][7],m[6][8])=0
    48                           // (m[6][9],...m[6][12]=v[6]
    49     //例2:n=6,w[6]=9,c=8,则(m[6][0],m[6][1],m[6][2],...m[6][8],m[6][9])=0
    50     
    51     //到此为止,已经求出可选择物品只有第n件时在重量k(0<=k<=c)情况下的最优值
    52     //接下来求可选择物品为(第n-1件、第n件),(第n-2件、第n-1件、第n件),...,(第2件、第3件...第n件) 在重量k(0<=k<=c)情况下的最优值
    53     for(i=n-1;i>1;i--)
    54     {
    55         jMax=w[i]-1<=c? w[i]-1:c;
    56         //jMax是使m[i][x]为0的x最后下标
    57         for(j=1;j<=jMax;j++) m[i][j]=m[i+1][j];
    58         //对于背包容量k(0<=k<=jMax),物品i是超重的,在这些容量下,一定不会选择物品i
    59         //即(m[i][1]=m[i+1][1],m[i][2]=m[i+1][2],...,m[i][jMax]=m[i+1][jMax];
    60         for(j=w[i];j<=c;j++) 
    61         {
    62             //对于背包容量k(w[i]<=k<=c),物品i是可容纳的,但是否一定选择物品i?
    63             t=w[i];
    64             m[i][j]=m[i+1][j]>=m[i+1][j-t]+v[i]?m[i+1][j]:m[i+1][j-t]+v[i];
    65             //以上语句你能看明白,这是0-1背包模型的关键
    66         }
    67         //到此为止,已经求出可选择物品为(第n-1件、第n件),(第 n-2件、第n-1件、第 n件),...,(第 2件、第 3件...第 n 件) 在重量 k(0<=k<=c)情况下的最优值
    68         //接下来是求可选择物品为(第 1件、第 2件...第 n件) 在重量 k(0<=k<=c)情况下的最优值吗?
    69         //No!只需求可选择物品为(第 1件、第 2件...第 n件) 在重量 c(真正的背包容量)下的最优值
    70         m[1][c]=m[2][c]; //假设不放入第一件物品
    71         t=w[1];
    72         if(w[1]<=c) m[1][c]=m[1][c]>=m[2][c-t]+v[1]?m[1][c]:m[2][c-t]+v[1];
    73         //可以容纳第一件物品的情况下,该如何选择?
    74     }
    75 }
    76 
    77 void Traceback(int v[],int w[],int c,int n,int m[][1000],int x[])
    78 {
    79     //v[]:价值,w[]:重量,c:背包可容纳重量,n:物品件数
    80     //m[][]:存放最大总价值的数组
    81     //m[i][j]表示背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值
    82     //x[i]表示是否放入第i件物品,1为是,0为否
    83     int i;
    84     for(i=1;i<n;i++)
    85       if(m[i][c]==m[i+1][c]) x[i]=0;
    86       //可选择物品中有第i件物品或没有第i件物品,最优值都是一样的,故一定没有放入第 i件物品
    87       else 
    88       {
    89             x[i]=1;
    90             c=c-w[i];
    91             //这个语句很重要,为判断是否选择了第 i+1件物品做准备
    92       }
    93       if(m[n][c]>0) //单独判断是否选择了第 n件物品
    94          x[i]=1;    
    95       else x[i]=0;
    96 }
  • 相关阅读:
    hdoj2187:悼念512汶川大地震遇难同胞 (贪心)
    2.0其它之Transform详解,以及UIElement和FrameworkElement的常用属性
    2.0外观之样式, 模板, 视觉状态和视觉状态管理器
    2.0图形之Ellipse, Line, Path, Polygon, Polyline, Rectangle
    2.0控件之ListBox, MediaElement, MultiScaleImage, PasswordBox, ProgressBar, RadioButton
    2.0画笔之SolidColorBrush, ImageBrush, VideoBrush, LinearGradientBrush, RadialGradientBrush
    2.0图形之基类System.Windows.Shapes.Shape
    2.0交互之鼠标事件和键盘事件
    2.0控件之ScrollViewer, Slider, StackPanel, TabControl, TextBlock, TextBox, ToggleButton
    2.0交互之InkPresenter(涂鸦板)
  • 原文地址:https://www.cnblogs.com/kunhu/p/3592998.html
Copyright © 2011-2022 走看看