背包問題優先隊列分枝限界演算法

來源:互聯網
上載者:User

這個大概是演算法課上的作業題。

所謂的背包問題,可以描述如下:一個小偷打劫一個保險箱,發現柜子裡有N類不同大小與價值的物品,但小偷只有一個容積為M的背包來裝東西,背包問題就是要找出一個小偷選擇所偷物品的組合,以使偷走的物品總價值最大。

這個問題的求解有很多種方法,本程式使用分枝限界法求解。

/*
  Copyright (c) 2006, 劉愛貴, Aigui.LIU@ihep.ac.cn, Computing Center of IHEP, Beijing, China
 */

//0/1背包問題優先隊列分枝限界演算法
#include "stdafx.h"
#include "iostream.h"
struct node{//結點表結點資料結構
                         node *parent;//父結點指標
                         node *next;  //後繼結點指標(優先隊列用)
                         int   level; //結點的級數
                         int   tag;   //標誌左右孩子
                         int   cu;    //背包剩餘空間
                         int   pe;    //已裝入物品有效益值
                         int   lb;    //結點的下界值
                         float ub;    //結點的上界值
                 };
class LcKnap{//優先隊列背包類
     private:
                 node *head;          //活動結點隊列隊頭
                 node *ANS,*E;        //解結點、根結點
                 int *p,*w;           //背包價值、重量數組指標
                 int M,lbb,cap,prof;  //背包容量、下限、剩餘容量、當前價值之和
                 int N;               //物品數
                 float L;             //裝入物品價值
                 float e,ubb;         //很小的正整數參量、價值上限
         public:
                  LcKnap(int *pp,int *ww,int MM,int NN,float ee);//建構函式
                 ~LcKnap();//解構函式
                 void  LUBound(int rw,int cp,int k,int &LBB,float &UBB);//計算上下界限
                 node* NewNode(node *parent,int level,int t,int cap,int prof,float ub,int lb);//產生一個新結點
                 void  EnQueue(node *i);//將結點i加入優先隊列
                 void  DeQueue(node *i);//將結點i從優先隊列中刪除
                 node* NextLiveNode();  //下一擴充結點
                 void  Print();         //列印結果
                 void  LCKNAP();        //背包問題求解
};
LcKnap::LcKnap(int *pp,int *ww,int MM,int NN,float ee)
{//建構函式
  int i;
  //初始化參數
  N=NN;
  M=MM;
  e=ee;
  p=new int[N];
  w=new int[N];
  for(i=0;i<N;i++)
  {
          p[i]=pp[i];
          w[i]=ww[i];
  }
  head=new(node);
  head->next=NULL;
  L=0;
  ANS=new(node);
}
LcKnap::~LcKnap()
{//解構函式
   delete head;
   delete p;
   delete w;
   delete ANS;
}
void LcKnap::LUBound(int rw,int cp,int k,int &LBB,float &UBB)
{//計算上下界限
        int i,j,c;
        LBB=cp;
    c=rw;
        for(i=k;i<N;i++)
        {
                if(c<w[i])
                {
                        UBB=(float)(LBB+c*p[i]/w[i]);
                        for(j=i+1;j<N;j++)
                        {
                                if(c>=w[j])
                                {
                                        c=c-w[j];
                                        LBB+=p[j];
                                }
                        }
                        return;
                }
                c=c-w[i];
                LBB+=p[i];
        }
        UBB=(float)LBB;
        return;
}
node* LcKnap::NewNode(node *parent,int level,int t,int cap,int prof,float ub,int lb)
{//產生一個新結點
        node* i=new(node);
        i->parent=parent;
        i->next=NULL;
        i->level=level;
        i->tag=t;
        i->cu=cap;
        i->pe=prof;
        i->ub=ub;
        i->lb=lb;
        return(i);
}
void LcKnap::EnQueue(node *i)
{//將結點i加入優先隊列
  i->next=head->next;
  head->next=i;
}
void LcKnap::DeQueue(node *i)
{//將結點i從優先隊列中刪除
   node *pre=head,*p=head->next;
   while(p!=i)
   {
           pre=p;
           p=p->next;
   }
   pre->next=p->next;
}
node *LcKnap::NextLiveNode()
{//下一擴充結點(取下限lb最大結點)
        node *p=head->next,*choice=p;
        int lb=p->lb;
        while(p)
        {
                if(p->lb>lb)
                {
                        choice=p;
                }
                p=p->next;
        }
        return(choice);
}
void LcKnap::Print()
{//列印結果
        int i;
        cout<<"Value Of Optimal Filling is:"<<L<<endl;
        cout<<"Objects In KnapSack Are:";
        for(i=N;i>=1;i--)
        {
                if(ANS->tag==1)
                {
                        cout<<'X'<<i<<' ';
                }
                ANS=ANS->parent;
        }
        cout<<endl<<endl;
}
void LcKnap::LCKNAP()
{//背包問題求解
   int i;
   node* E=new(node);  //根結點
   E->parent=NULL;
   E->next=NULL;
   E->level=0;
   E->cu=M;
   E->pe=0;
   E->tag=0;
   LUBound(M,0,0,lbb,ubb);//計算根結點上下界限
   L=lbb-e;
   E->lb=lbb;
   E->ub=ubb;
   while(E->ub>L)    //當前擴充結點上界<當前解時結束
   {
           i=E->level;
           cap=E->cu;
           prof=E->pe;
           if(i==N)  //解結點
           {
                   if(prof>L)
                   {
                           L=(float)prof;   //解
                           ANS=E;
                   }
           }
           else              //E有兩個兒子
           {
                   if(cap>=w[i]) //左兒子可行
                   {
              EnQueue(NewNode(E,i+1,1,cap-w[i],prof+p[i],E->ub,E->lb));
                   }
           LUBound(cap,prof,i+1,lbb,ubb);  //重新計算上下界    
                   if(ubb>L)   //右兒子可行
                   {
              EnQueue(NewNode(E,i+1,0,cap,prof,ubb,lbb));
                          if(L<lbb-e)L=lbb-e;
                   }
           }
           if(head->next==NULL)//隊列空或ub>L結束
           {
                   break;
           }
           else
           {
                   E=NextLiveNode();   //下一擴充結點
                   DeQueue(E);         //將結點從隊列中刪除
           }
   }//EndWhile
   Print();
}
//主程式
void main(int argc, char* argv[])
{
        float e;
        int p[4]={10,10,12,18},w[4]={2,4,6,9};// 4背包
        int pp[16]={10,12,9,15,13,12,10,14,9,7,19,18,15,12,11,10}; //16背包 
        int ww[16]={ 2, 3,3, 5, 5, 6, 5, 7,5,4,12,14,12,12,13,14};
        e=(float)0.0001;
        LcKnap *knap4 =new LcKnap(p,w,15,4,e);
        LcKnap *knap16=new LcKnap(pp,ww,40,16,e);
        knap4->LCKNAP();
        knap16->LCKNAP();

        delete knap4;
        delete knap16;
}
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.