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 }
  • 相关阅读:
    day06.2-软链接与硬链接
    day06.1-磁盘管理
    day05.3-Linux进程管理
    day05.2-Vim编辑器
    day05.1-文件归档与压缩
    day04-Linux系统中用户控制及文件权限管理方法
    day03-Linux操作系统目录结构
    day02.2-常用Linux命令整理
    BST_traverse(中序遍历,前序遍历,后序遍历)
    JS_DOM_practice with Pokemon
  • 原文地址:https://www.cnblogs.com/kunhu/p/3592998.html
Copyright © 2011-2022 走看看