分支限界法之LC 0/1背包

来源:互联网 发布:阿里云宽带 编辑:程序博客网 时间:2024/06/06 13:59
  1. 1.问题描述:已知有N个物品和一个可以容纳M重量的背包,每种物品I的重量为WEIGHT,一个只能全放入或者不放入,求解如何放入物品,可以使背包里的物品的总效益最大。
  2.  
  3. 2.设计思想与分析:对物品的选取与否构成一棵解树,左子树表示不装入,右表示装入,通过检索问题的解树得出最优解,并用结点上界杀死不符合要求的结点。
  4.  
  5. (多谢shadow同学提供该算法)
  6.  
  7. #include <iostream.h>
  8.  
  9. struct good
  10. {
  11.  int weight;
  12.  int benefit;
  13.  int flag;//是否可以装入标记
  14. };
  15.  
  16. int number=0;//物品数量
  17. int upbound=0;
  18. int curp=0, curw=0;//当前效益值与重量
  19. int maxweight=0;
  20. good *bag=NULL;
  21.  
  22. void Init_good()
  23. {
  24.  bag=new good [number];
  25.  
  26.  for(int i=0; i<number; i++)
  27.  {
  28.   cout<<"请输入第件"<<i+1<<"物品的重量:";
  29.   cin>>bag[i].weight;
  30.   cout<<"请输入第件"<<i+1<<"物品的效益:";
  31.   cin>>bag[i].benefit;
  32.   bag[i].flag=0;//初始标志为不装入背包
  33.   cout<<endl;
  34.  }
  35.  
  36. }
  37.  
  38. int getbound(int num, int *bound_u)//返回本结点的c限界和u限界
  39. {
  40.  for(int w=curw, p=curp; num<number && (w+bag[num].weight)<=maxweight; num++)
  41.  {
  42.   w=w+bag[num].weight;
  43.   p=w+bag[num].benefit;
  44.  }
  45.  
  46.  *bound_u=p+bag[num].benefit;
  47.  return ( p+bag[num].benefit*((maxweight-w)/bag[num].weight) );
  48. }
  49.  
  50. void LCbag()
  51. {
  52.  int bound_u=0, bound_c=0;//当前结点的c限界和u限界
  53.  
  54.  for(int i=0; i<number; i++)//逐层遍历解树决定是否装入各个物品
  55.  {
  56.   if( ( bound_c=getbound(i+1, &bound_u) )>upbound )//遍历左子树
  57.     upbound=bound_u;//更改已有u限界,不更改标志  
  58.  
  59.   if( getbound(i, &bound_u)>bound_c )//遍历右子树
  60.   //若装入,判断右子树的c限界是否大于左子树根的c限界,是则装入
  61.   {
  62.    upbound=bound_u;//更改已有u限界
  63.    curp=curp+bag[i].benefit;
  64.    curw=curw+bag[i].weight;//从已有重量和效益加上新物品
  65.    bag[i].flag=1;//标记为装入
  66.   }
  67.  }
  68.  
  69. }
  70.  
  71. void Display()
  72. {
  73.  
  74.  cout<<"可以放入背包的物品的编号为:";
  75.  for(int i=0; i<number; i++)
  76.   if(bag[i].flag>0)
  77.    cout<<i+1<<" ";
  78.   cout<<endl;
  79.   delete []bag;
  80. }
  81.  
原创粉丝点击