• 分支限界法 0-1背包问题-优先队列式


      1 #include<iostream>
      2 #include<queue>
      3 using namespace std;
      4 
      5 const int maxn=99; 
      6 int n,c;
      7 int w[maxn];
      8 int v[maxn];
      9 
     10 int bestv=0;
     11 int bestx[maxn];
     12 int total=1;        //解空间中的节点数累计,全局变量 
     13 struct nodetype        //队列中的结点类型
     14 {
     15     int no;            //结点编号,从1开始 
     16     int i;            //当前结点在搜索空间中的层次 
     17     int w;            //当前结点的总重量 
     18     int v;            //当前结点的总价值 
     19     int x[maxn];    //当前结点包含的解向量 
     20     double ub;        //上界 
     21     bool operator<(const nodetype &s)const //重载<关系函数
     22     {
     23         return ub<s.ub;   //ub越大越优先出队 
     24      } 
     25 };
     26 
     27 void input()
     28 {
     29     cout<<"请输入物品的个数:"<<endl;
     30     cin>>n;
     31     cout<<"请输入每个物品的重量及价值(如5 4):"<<endl;
     32     for(int i = 1; i <= n; i++)
     33     {
     34         cin>>w[i]>>v[i];
     35     }
     36     cout<<"请输入背包的容量:"<<endl;
     37     cin>>c;
     38 }
     39 
     40 void bound(nodetype &e)        //计算分支结点e的上界 
     41 {
     42     int i=e.i+1;        //考虑结点e的余下物品
     43     int sumw=e.w;
     44     double sumv=e.v;
     45     while((sumw+w[i]<=c)&&i<=n) 
     46     {
     47         sumw+=w[i];
     48         sumv+=v[i];
     49         i++;
     50     }
     51     if(i<=n)            //余下物品只能部分装入 
     52     e.ub=sumv+(c-sumw)*v[i]/w[i];
     53     else e.ub=sumv; 
     54 } 
     55 
     56 void enqueue(nodetype e,priority_queue<nodetype> &qu)
     57 //结点e进队qu 
     58 {
     59     if(e.i==n)                //到达叶子节点,不在扩展对应一个解 
     60     {
     61         if(e.v>bestv)        //找到更大价值的解 
     62         {
     63             bestv=e.v;
     64             for(int j=1;j<=n;j++)
     65             bestx[j]=e.x[j];
     66         }
     67     }
     68     else qu.push(e);        //非叶子结点进队
     69 } 
     70 
     71 void bfs()
     72 {
     73     int j;
     74     nodetype e,e1,e2;
     75     priority_queue<nodetype> qu;
     76     
     77     e.i=0;
     78     e.w=0;
     79     e.v=0;
     80     e.no=total++;
     81     
     82     for(j=1;j<=n;j++)
     83     e.x[j]=0;
     84     bound(e);
     85     qu.push(e);
     86     
     87     while(!qu.empty())
     88     {
     89         e=qu.top();qu.pop();    //出队结点e 
     90         if(e.w+w[e.i+1]<=c)        //剪枝,检查左孩子结点 
     91         {
     92             e1.no=total++;        //建立左孩子结点 
     93             e1.i=e.i+1;
     94             e1.w=e.w+w[e1.i];
     95             e1.v=e.v+v[e1.i];
     96             for(j=1;j<=n;j++)
     97             e1.x[j]=e.x[j];
     98             e1.x[e1.i]=1;
     99             bound(e1);        //求左孩子的上界 
    100             enqueue(e1,qu);    //左孩子结点进队 
    101         }
    102         e2.no=total++;
    103         e2.i=e.i+1;
    104         e2.w=e.w;
    105         e2.v=e.v; 
    106         for(j=1;j<=n;j++)
    107             e2.x[j]=e.x[j];
    108         e2.x[e2.i]=0;
    109         bound(e2);
    110         if(e2.ub>bestv)        //若右孩子结点可行,则进队,否则被剪枝 
    111         enqueue(e2,qu);    
    112     }
    113 } 
    114 
    115 void output()
    116 {
    117     cout<<"最优值是:"<<bestv<<endl;
    118     cout<<"(";
    119     for(int i=1;i<=n;i++)
    120         cout<<bestx[i]<<" ";
    121     cout<<")";
    122 }
    123 
    124 int main()
    125 {
    126     input();
    127     bfs();
    128     output();
    129     return 0;
    130  } 
  • 相关阅读:
    Asp.Net Winform 条形码系列之Code39 Code39 Of .Net BarCode Serial Blog
    .NET 中文星期几的简单实现方式
    C#使用SQLite数据库(asp.net/winform)
    .Net日期时间格式化输出大全 DateTime.ToString(?)
    C#使用HTTP头检测网络资源是否有效
    [转]C#(VB.NET)操作Windows自带的防火墙 之 添加/删除允许通过防火墙的例外程序
    华为C2800进入工程模式
    android webview 加载网页显示对话框
    SVN 与 VS2003
    VisualSVN1.7.7 序列号
  • 原文地址:https://www.cnblogs.com/yuanqingwen/p/12909823.html
Copyright © 2020-2023  润新知