回溯法解决0-1背包问题----迭代

#include <iostream>
#include <algorithm>
#include <iomanip>
using  namespace std;
typedef struct  Thing{
    double weight;
    double value;
    int index;
};
Thing *things;
const int goods = 7;//物品的数量
int Max_Weight = 150;//背包承受的重量
int information[2][goods] = {{35, 30, 60, 50, 40, 10, 25}, {10, 40, 30, 50, 35, 40, 30}};//第一行为重量,第二行为价值
int solution[goods];//解空间
int Best_solution[goods];//最优解向量
int Best_value = 0;//最优解的价值
int Best_weight = 0;//最优解的重量
bool cmp(Thing &t1, Thing &t2)//重定义sort
{
    return (t1.value / t1.weight) > (t2.value / t2.weight);
}
double get_best_value(int t, int limit_weight)//完全背包问题即限界函数的参数比较
{
    double sum_weight = 0, sum_value = 0;
    int i;
    for( i = t; i < goods; i++)
    {
        if(sum_weight + things[i].weight > limit_weight)
            break;
        else{
            sum_value += things[i].value;
            sum_weight += things[i].weight;
        }
    }
    if(i < goods && limit_weight > sum_weight)
    {
        sum_value += (limit_weight - sum_weight) * things[i].value / things[i].weight;
    }
    return sum_value;
}
void IterativeBacktrack(int t, int cv, int cw)//t 为
{
    while(t >= 0)
    {
        while(t < goods && cw - things[t].weight >= 0)//直接装包至不能装,及直接遍历解空间的左孩子,及利用约束函数
        {
            solution[t] = 1;
            cw -= things[t].weight;
            cv += things[t].value;
            t++;
        }
        if(t >= goods)//已经把能装的装了,又因为限界函数和约束函数,此解比之前Best_solutio更好,更新输出
        {
            for(int i = 0; i < goods; i++)
                Best_solution[i] = solution[i];
            for(int i = 0; i < goods; i++)
                cout << " " << solution[i];
            cout << "  value : " << cv << endl;
            Best_value  = cv;
        } else//否则丢下
        {
            solution[t] = 0;
            t++;//保证不能装的情况下不陷入死循环,课以注释掉试一下
        }
        while(get_best_value(t, cw) + cv <= Best_value)//利用限界函数剪枝,如果之后不会获得更优解则回调到可能获得更优解的结点
        {
            t--;
            while (t >= 0 && solution[t] == 0)//回调到装物品的结点
                t--;
            if (t < 0)
                break;
            solution[t] = 0;//不装该物品
            cw -= things[t].weight;//更新数据
            cv -= things[t].value;
        }
    }
}
int main()
{
    things = new Thing[goods];
    for(int i = 0; i < goods; i++)
    {
        things[i].weight = information[0][i];
        things[i].value = information[1][i];
        things[i].index = i;
    }
    sort(things, things + goods, cmp);
    IterativeBacktrack(0, 0, Max_Weight);
    //获得物品的编号
    vector<int> pos;
    for(int i = 0; i < goods; i++)
        if(Best_solution[i] == 1)
            pos.push_back(things[i].index);
    sort(pos.begin(), pos.end());
    cout <<  "装入背包的编号: " << endl;
    for(int i = 0; i < pos.size(); i++)
        cout << " " << pos[i] + 1;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值