zoukankan      html  css  js  c++  java
  • 回溯法 0-1背包问题

    一.回溯法

    回溯法采用的是深度优先策略,回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。
    (1)三个步骤:
        1.针对所给问题,定义问题的解空间;
        2.确定易于搜索的解空间结构;
       3. 以深度优先的方式搜索解空间。
    (2)优化方法:
    搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:
        1.使用约束函数,剪去不满足约束条件的路径。
        2.使用限界函数,剪去不能得到最优解的路径。

    (3)解空间树的类型分为排列树和子集树。

    二.0-1背包问题

    问题:给定n种物品和一背包。物品i的重量是wi,其价值为pi,背包的容量为C。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

     1 #include <iostream>
     2 using namespace std;
     3  
     4 #define N 100   //默认有99个物品。第一个不使用
     5 int w[N];    //每个物品的重量
     6 int v[N];    //每个物品的价值
     7 int x[N];     //x[i]=1:物品i放入背包,0代表不放入
     8 int n,c;       //n:一共有多少物品,c:背包的最大容量
     9 
    10 int CurWeight = 0;  //当前放入背包的物品总重量
    11 int CurValue = 0;   //当前放入背包的物品总价值
    12 
    13 int BestValue = 0;  //最优值;当前的最大价值,初始化为0
    14 int BestX[N];       //最优解;BestX[i]=1代表物品i放入背包,0代表不放入
    15 
    16 /*
    17 *回溯函数 参数t表示当前处在第几层做抉择,t=1时表示当前在决定是否将第一个物品放入背包
    18 */
    19 void backtrack(int t)
    20 {
    21     //叶子节点,输出结果
    22     if(t>n)
    23     {
    24         //如果找到了一个更优的解
    25         if(CurValue>BestValue)
    26         {
    27             //保存更优的值和解
    28             BestValue = CurValue;
    29             for(int i=1; i<=n; ++i)
    30                 BestX[i] = x[i];
    31         }
    32     }
    33     else
    34     {
    35         //遍历当前节点的子节点:0 不放入背包,1放入背包
    36         for(int i=0; i<=1; ++i)
    37         {
    38             x[t]=i;
    39  
    40             if(i==0) //不放入背包
    41             {
    42                 backtrack(t+1);
    43             }
    44             else //放入背包
    45             {
    46                 //约束条件:当前物品是否放的下
    47                 if((CurWeight+w[t])<=c)
    48                 {
    49                     CurWeight += w[t];
    50                     CurValue += v[t];
    51                     backtrack(t+1);
    52                     CurWeight -= w[t];
    53                     CurValue -= v[t];
    54                 }
    55             }
    56         }
    57     }
    58 }
    59  
    60 int main()
    61 {
    62  
    63     cout<<"请输入物品的个数:"<<endl;
    64     cin>>n;
    65     cout<<"请输入每个物品的重量及价值(如5 4):"<<endl;
    66     for(int i = 1; i <= n; i++)
    67     {
    68         cin>>w[i]>>v[i];
    69     }
    70     cout<<"请输入背包的限制容量:"<<endl;
    71     cin>>c;
    72     
    73     backtrack(1);
    74     
    75     cout<<"最优值是:"<<BestValue<<endl;
    76     cout<<"(";
    77     for(int i=1;i<=n;i++)
    78         cout<<BestX[i]<<" ";
    79     cout<<")";
    80     return 0;
    81 }
     1 #include <iostream>
     2 using namespace std;
     3  
     4 #define N 100   //默认有99个物品。第一个不使用
     5 int w[N];    //每个物品的重量
     6 int v[N];    //每个物品的价值
     7 int x[N];     //x[i]=1:物品i放入背包,0代表不放入
     8 int n,c;       //n:一共有多少物品,c:背包的最大容量
     9 
    10 int CurWeight = 0;  //当前放入背包的物品总重量
    11 int CurValue = 0;   //当前放入背包的物品总价值
    12 
    13 int BestValue = 0;  //最优值;当前的最大价值,初始化为0
    14 int BestX[N];       //最优解;BestX[i]=1代表物品i放入背包,0代表不放入
    15  
    16 void input()
    17 {
    18     cout<<"请输入物品的个数:"<<endl;
    19     cin>>n;
    20     cout<<"请输入每个物品的重量及价值(如5 4):"<<endl;
    21     for(int i = 1; i <= n; i++)
    22     {
    23         cin>>w[i]>>v[i];
    24     }
    25     cout<<"请输入背包的容量:"<<endl;
    26     cin>>c;
    27 }
    28 void output()
    29 {
    30     cout<<"最优值是:"<<BestValue<<endl;
    31     cout<<"(";
    32     for(int i=1;i<=n;i++)
    33         cout<<BestX[i]<<" ";
    34     cout<<")";
    35  
    36 }
    37 /*
    38 *回溯函数 参数t表示当前处在第几层做抉择,t=1时表示当前在决定是否将第一个物品放入背包
    39 */
    40 void backtrack(int t,int CurWeight,int CurValue,int rw,int x[])
    41 {
    42     //初始调用时rw为所有物品重量和 
    43     if(t>n)
    44     {
    45         //如果找到了一个更优的解
    46         if(CurWeight==c&&CurValue>BestValue)
    47         {
    48             //保存更优的值和解
    49             BestValue = CurValue;
    50             for(int i=1; i<=n; ++i)
    51                 BestX[i] = x[i];
    52         }
    53     }
    54     else
    55     {
    56         //遍历当前节点的子节点:0 不放入背包,1放入背包
    57         if(CurWeight+w[t]<=c) //左孩子结点剪枝 
    58         {
    59             x[t]=1;//选取第i个物品回溯 
    60             backtrack(t+1,CurWeight+w[t],CurValue+v[t],rw-w[t],x);
    61         }
    62         x[t]=0;//不选取第i个物品回溯 
    63         if(CurWeight+rw>c)//右孩子结点剪枝 
    64         backtrack(t+1,CurWeight,CurValue,rw-w[t],x);        //rw都减去w[t]代表已经考虑过是否选取当前物品,不必再考虑 
    65     }
    66  
    67 }
    68  
    69 int main()
    70 {
    71  
    72     input();
    73     backtrack(1,0,0,11,x);
    74     output();
    75     return 0;
    76 }

     

  • 相关阅读:
    应用机器学习建议
    梯度下降法解神经网络
    梯度下降法解逻辑斯蒂回归
    线性代数学习笔记(十四)
    线性代数学习笔记(十三)
    线性代数学习笔记(十二)
    线性代数学习笔记(十一)
    线性代数学习笔记(十)
    线性代数学习笔记(九)
    重新编译Unity Mono遇到的坑,大坑,巨坑!!!
  • 原文地址:https://www.cnblogs.com/yuanqingwen/p/12904317.html
Copyright © 2011-2022 走看看