0
点赞
收藏
分享

微信扫一扫

算法回溯法-0-1背包c++

陬者 2022-04-14 阅读 39
c++算法
// 回溯法0-1背包.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
思路差异:
// 解为子集树:<=c,可进入左子集;>maxvule,则可以进入由结点
// 
// 


#include <iostream>
#include <algorithm>
using namespace std;
class Knap {
public:
    void Backtrack(int i);
    int bound(int i);
    int c,//背包总容量
        n,//物品总数量
        * w,//物品重量数组
        * p,//物品价值数组
        cw,//当前总重量
        cp,//当前总价值
        bestp,//当前最优价值
        * x;//是否放入
};
//puplic:
void Knap::Backtrack(int i) //标记了类名,函数体中才可以访问类中属性!!
{
    if (i > n)
    {
        bestp = cp;
      /*  if (cp > bestp)//不需要,上限函数的比较对象不是bestp
        {
        }*/
        return;
    }
    //能否放下进入左子树:
    if (cw + w[i] <= c)
    {
        cw += w[i];
        cp += p[i];
        x[i] = 1;
        Backtrack(i + 1);
        //返回上一结点,需要恢复场景
        cw -= w[i];
        cp -= p[i];
    }
    //判断最优解:进入右子树
    //最优的可能下的解>bestp:即cp+p[++1]...+(p[j]/w[j])*cleft>bestp;
    if (bound(i+1)> bestp)//i不放入,bound(i)是从w[i]开始相加所以不考虑i!!!!
    {
        x[i] = 0;
        Backtrack(i + 1);
    }

}

//求出可能存在的最优解,即cp+p[++1]...+(p[j]/w[j])*cleft>bestp;单价按照高到低排列
int Knap::bound(int i)
{
    int cleft = c - cw;
    int b = cp;//当前的总价值和
    int j = i;

    while (j<=n&&cleft >= w[j])//能放下的,不会超过个数也能大于w[j]
    {
        cleft -= w[j];
        b += p[j];
        j++;
    }

    if (j <=n)//背包装不下w[j]了
    {
        b += (p[j] / w[j]) * cleft;
    }
    /*b += (p[j] / w[j]) * cleft;*/
    return b;
}
class object//物品性质
{
public:
    int Knapsack(int p[], int w[], int c, int n);
    float aver;//p[]/w[]
    int index;
    //标号
};
//用于初始化返回最优
int object ::Knapsack(int p[], int w[], int c, int n)
{
    object* q = new object[n];//物品数组对象
    for (int i = 0; i < n; i++)
    {
        q[i].index = i;
        q[i].aver = p[i] * 1.0 / w[i];
    }
    //sort(q,q+5 );//单价升序//按照aver排的??
    float temp;
    冒泡排序
   // sort(q[0].aver, q[4].aver);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j <n-i-1; j++)
        {
            if (q[j].aver < q[j + 1].aver)
            {
                temp = q[j].aver;
                q[j].aver = q[j + 1].aver;
                temp = q[j + 1].aver;
            }
        }
    }
    Knap bag;
    bag.p = new int[n];
    bag.w = new int[n];
    for (int i = 0; i < n; i++)
    {
        bag.p[i] = p[q[i].index];
        bag.w[i] = w[q[i].index];
    }
    bag.cp = 0, bag.cw = 0;//初始值
    bag.c = c;
    bag.n = n;
    bag.bestp = 0;
    bag.Backtrack(1);
    cout << "放入的物品有:\n";
    for (int i = 0; i < n; i++)
    {
        if (bag.x[i] == 1)
            cout << "z重量:" << w[i] << "价值为:" << p[i] << endl;
    }
    delete []q;
    delete []bag.p;
    delete[]bag.w;
    return bag.bestp;
}

int main()
{
    int n = 5;
    int c = 10;
    //bag.c = 10;//背包总容量!
    //bag.n = 5;//物品总个数
    int w[] = { 2,5,3,2,1 };
    int p[] = { 2,7,3,3,2 };
    object k;
    k.Knapsack(p, w, c, n);
    cout << "最优价值" << k.Knapsack(p, w, c, n)<<endl;
    
}
举报

相关推荐

0 条评论