1. 程式人生 > >分支界限法與優先佇列發求解揹包問題

分支界限法與優先佇列發求解揹包問題

#include <iostream>
#include<queue>
#define N 5
#define W 10
/*
2 6
2 3
6 5
5 4
4 6
測試用例
另:solve1()為佇列式分支界限法求解結果
solve2()為優先佇列式分支界限法求解結果
*/
using namespace std;
class Pack
{
    public:
    int cw,cp,isleft,level;
    Pack *parent;
    Pack(){}
    Pack(int weight,int value,int Isleft,int Level,Pack* p)
    {
        cw=weight;
        cp=value;
        isleft=Isleft;
        level=Level;
        parent=p;
    }
};
class Pack1
{
    public:
    int cw,cp,isleft,level,up;
    Pack1 *parent;
    Pack1(){}
    Pack1(int weight,int value,int Isleft,int Level,Pack1* p,int Up)
    {
        cw=weight;
        cp=value;
        isleft=Isleft;
        level=Level;
        parent=p;
        up=Up;
    }
};
struct cmp
{
    bool operator()(Pack1 *&a, Pack1 *&b) const
    {
        return a->up < b->up;
    }
};
class solve
{
    public:
    int *w,*v,*X1,*X2,bestp1,bestp2;

    solve()
    {
        int i=0;
        w=new int[N];
        v=new int[N];
        X1=new int[N];
        X2=new int[N];
        bestp1=0;
        bestp2=0;
        for (i=0;i<N;i++)
        {
            cin>>w[i]>>v[i];
            X1[i]=0;
            X2[i]=0;
        }

    }
    void answer1copy(Pack *qnode)
    {
         int i=N-1;
         while(qnode!=NULL)
         {
             if(qnode->isleft==1)
             {
                   X1[i]=1;

             }
             else
                {
                    X1[i]=0;
                }
             i--;
             qnode=qnode->parent;
         }
    }
    void answer2copy(Pack1 *qnode)
    {
        int i=N-1;
         while(qnode!=NULL)
         {
             if(qnode->isleft==1)
             {
                   X2[i]=1;

             }
             else
                {
                    X2[i]=0;
                }
             i--;
             qnode=qnode->parent;
         }

    }
    int BOUND(int i)
    {
        int j,sum=0;
        for (j=i;j<N;j++)
        {
            sum+=v[j];
        }
        return sum;
    }
    void solve1()
    {
        queue<Pack*> qpack;
        int cw,cp,bestp,i;

        i=0;
        cw=0;
        cp=0;
        bestp=0;
        Pack *qNode=NULL,*qNode1=NULL;
        if (cw+w[i] <= W) //左子結點. 這裡也可以考慮限界條件
                {

                   bestp=(cp+v[i]>bestp) ? cp+v[i] : bestp;
                   qNode1=new Pack(cw+w[i],cp+v[i],1,i+1,qNode);
                   qpack.push(qNode1);

                }
                if (BOUND(i+1)+cp >= bestp) //右子結點. BOUND為限界函式
                   {

                       qNode1=new Pack(cw,cp,0,i+1,qNode);
                       qpack.push(qNode1);

                   }
         while (1)
        {

                qNode=qpack.front();
                if(qNode==NULL)
                   {
                       break;
                   }

                   cw = qNode->cw;
                   cp = qNode->cp;
                   i = qNode->level;
                if ((qNode->level == N)&& (qNode->cp  >= bestp))
            {
                bestp1=bestp;
                answer1copy(qNode);
            }
                if(i<N)
                    {
                if (cw+w[i] <= W) //左子結點. 這裡也可以考慮限界條件
                {

                   bestp=(cp+v[i]>bestp) ? cp+v[i] : bestp;
                   qNode1=new Pack(cw+w[i],cp+v[i],1,i+1,qNode);
                   qpack.push(qNode1);

                }
                if (BOUND(i+1)+cp >= bestp) //右子結點. BOUND為限界函式
                   {

                       qNode1=new Pack(cw,cp,0,i+1,qNode);
                       qpack.push(qNode1);

                   }
                   }
                   qpack.pop();



            }


                }



        void solve2()
    {
        priority_queue<Pack1 *, vector<Pack1 *>, cmp > qpack;
        int cw,cp,bestp,i;

        i=0;
        cw=0;
        cp=0;
        bestp=0;
        Pack1 *qNode=NULL,*qNode1=NULL;
        if (cw+w[i] <= W) //左子結點. 這裡也可以考慮限界條件
                {

                   bestp=(cp+v[i]>bestp) ? cp+v[i] : bestp;
                   qNode1=new Pack1(cw+w[i],cp+v[i],1,i+1,qNode,BOUND(i)+cp);
                   qpack.push(qNode1);

                }
                if (BOUND(i+1)+cp >= bestp) //右子結點. BOUND為限界函式
                   {

                       qNode1=new Pack1(cw,cp,0,i+1,qNode,BOUND(i+1)+cp);
                       qpack.push(qNode1);

                   }
         while (1)
        {

                qNode=qpack.top();
                if(qNode==NULL)
                   {
                       break;
                   }

                   cw = qNode->cw;
                   cp = qNode->cp;
                   i = qNode->level;
                if ((qNode->level == N)&& (qNode->cp  >= bestp))
            {
                bestp2=bestp;
                answer2copy(qNode);
                break;
            }
                if(i<N)
                    {
                if (cw+w[i] <= W) //左子結點. 這裡也可以考慮限界條件
                {

                   bestp=(cp+v[i]>bestp) ? cp+v[i] : bestp;
                   qNode1=new Pack1(cw+w[i],cp+v[i],1,i+1,qNode,BOUND(i)+cp);
                   qpack.push(qNode1);

                }
                if (BOUND(i+1)+cp >= bestp) //右子結點. BOUND為限界函式
                   {

                       qNode1=new Pack1(cw,cp,0,i+1,qNode,BOUND(i+1)+cp);
                       qpack.push(qNode1);

                   }
                   }
                   qpack.pop();



            }


    }
};


int main()
{
    solve s;
    s.solve1();
    s.solve2();

    cout <<"佇列式分支界限法求解結果:"<<endl<< "the best value is  "<<s.bestp1 <<"  "<< endl<<"selected packages are ";
    for (int i=0;i<N;i++)
    {
        if(s.X1[i]==1)
        {
            cout<<"No."<<i+1<<" ";
        }
    }
    cout<<endl;
    cout <<"優先佇列式分支界限法求解結果:"<<endl<< "the best value is  "<<s.bestp2 <<"  "<< endl<<"selected packages are ";
    for (int i=0;i<N;i++)
    {
        if(s.X2[i]==1)
        {
            cout<<"No."<<i+1<<" ";
        }
    }
    cout<<endl;
    return 0;
}