分支定界算法(c++)

用c++也写了分支定界算法,解决背包问题。

参考:https://www.geeksforgeeks.org/implementation-of-0-1-knapsack-using-branch-and-bound/

#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
//分支定界算法,使用深度优先的栈实现

//节点类实现
class Node
{    
public:
    int curvalue; //当前节点的价值
    int level = -1;
    int room;
    double bestvalue; //bound值
    bool flag = 1;   
    vector<int> bit; //最优解集
};
//物体属性
class Item
{
public:
    int index;
    int value;
    int weight;
};

//自定义比较函数,对items进行排序
bool mycompare(const Item a, const Item b)
{
    double a_den = a.value * 1.0 / a.weight;
    double b_den = b.value * 1.0 / b.weight;
    return a_den > b_den;
}

//branch & bound ,dfs implementation
class Bound
{
public:
/***************初始化Item数据**************/
    Bound()
    {
        ifstream fin("./data/ks_10000_0");                        
        string line;
        stringstream stream;
        if(getline(fin, line))
        {    
            stream.clear();
            stream << line;
            stream >> item_count;
            stream >> capacity;    
        }
//        maxprofit = 0;
        int cnt = 0;
        while(getline(fin, line))
        {
            int value;
            int weight;
            Item item;
            stream.clear();
            stream << line;
            stream >> value;
            stream >> weight;
            //maxprofit += value;
            item.index = cnt;
            item.value = value;
            item.weight = weight;
            items.push_back(item);
            cnt++;
        }
        //排序
        sort(items.begin(), items.end(), mycompare);

    }
    //计算bound,好的bound对有效地剪枝(prune)很重要
    double bound( Node a )
    {
        double sum = 0;
        double weight = 0;
        if(a.level == -1){
            for(int i = 0; i < item_count; i++)
            {
                if(weight + items[i].weight <= capacity)
                {
                    sum += items[i].value;
                    //cout << "sum :" << sum << endl;
                    weight += items[i].weight;
                } else {
                    sum += (capacity-weight)*1.0 / items[i].weight  * items[i].value;
                    //cout << "sum:" << sum << endl;
                    break;
                }    
            }
        } else {
            sum += a.curvalue;
            weight += capacity - a.room;
            for(int i = a.level+1; i < item_count; i++)
            {
                if(weight + items[i].weight <= capacity)
                {
                    sum += items[i].value;
                //    cout << "sum :" << sum << endl;
                    weight += items[i].weight;
                } else {
                    sum += (capacity-weight)*1.0 / items[i].weight  * items[i].value;
                //    cout << "sum:" << sum << endl;
                    break;
                }    
            }        
        }
        return sum;
    }


    void print(Node a)
    {
        cout   <<  "level:" << a.level <<  "curvalue:" << a.curvalue << ","  << "room:" << a.room << "," <<  "bestvalue:" << a.bestvalue << endl;
    
    }
    //深度优先的branch & bound
    int dfs()
    {
        Node u, v;
        u.curvalue = 0;
        u.room = capacity;
        u.bit.resize(item_count);    
        u.bestvalue = bound(u);
    //    print(u);
        myQ.push(u);
        int max = 0;
        int cnt = 0;
        while(!myQ.empty())
        {
            cout << "cnt:" << cnt ++ << endl;
            u = myQ.top();
            myQ.pop();
            if(u.level == -1)
            {
                v.level = 0;
            }

            if(u.level == item_count-1)
            {
                continue;
            }
            //not choose this item;
            v.level = u.level + 1;
            v.room = u.room;
            v.curvalue = u.curvalue;
            //cout << "curvalue:"     << v.curvalue << endl;
            v.bestvalue = bound(v);
            v.bit = u.bit;
        
            if(v.bestvalue > max)
            {
                myQ.push(v);
                if(v.level == item_count - 1 )
                {
                    max = v.curvalue;
                    bit = v.bit;
                //    cout << "max value: " << max << endl;
                }
            }
            
            //choose this item;
            v.level = u.level + 1;
            v.room = u.room - items[v.level].weight;
            v.curvalue = u.curvalue +  items[v.level].value;
            v.bit = u.bit;
            v.bit[items[v.level].index] = 1;
            v.bestvalue = u.bestvalue;
            if((v.room >= 0) && (v.bestvalue > max))
            {
                myQ.push(v);
                if(v.level == item_count - 1 )
                {
                    max = v.curvalue;
                    bit = v.bit;
                }
            }
        }

        return max;
    }
    
    void printbit()
    {
        for(int i = 0; i < bit.size(); i++)
        {
            cout << bit[i] << " ";
        }
    }

public:
//    int maxprofit; 
    vector<int> bit; //保留最优解集
    vector<Item> items;  //物体数组
    int item_count; //物体数目
    int capacity;   //背包容量
    stack<Node> myQ; //stack 栈,后进先出
};

int main()
{    
    clock_t start, end;
    start = clock();
    Bound bound;
    cout << "maxprofit:" << bound.dfs() << endl;
    bound.printbit();
    end = clock();
    cout << "running time:" << (double)(end-start)/CLOCKS_PER_SEC << "s" << endl;
    return 0;
}
The Safest Way to Get what you Want is to Try and Deserve What you Want.
原文地址:https://www.cnblogs.com/Shinered/p/9711297.html