// 回溯法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;
}