/***************************************/
/* 0/1背包问题(物体不可分割) */
/*求装入背包的物体及其总价值 */
/***************************************/
#include<iostream>
#include<iomanip>
#define N 20 //最多物体个数
#define M 100 //最大背包载重量
using namespace std;
typedef struct{
float w; // 物体重量
float p; // 物体价值
float v; // 物体的价值重量比
} OBJECT;
int main(){
/*函数声明*/
void create_wuti(OBJECT T[], int t);
void bubble_sort(OBJECT A[], int n);
float knapsack_back(OBJECT ob[],float m,int n,bool x[]);
OBJECT ob[N]; //物体
float m; // 背包载重量
bool x[N]; // 可能的解向量
int n;
cout << "请输入物体个数n(不超过20)及背包载重量m(100)分别为:";
cin >> n >> m;
cout << "\n-----创建物体的重量及其价值-----";
create_wuti(ob,n);
int v = knapsack_back(ob,m,n,x);
cout << "\n背包中物体的最大价值为:" << v;
cout << "\n解向量为:";
for (int i = 0;i<n; i++)
cout << x[i] << " ";
cout<<endl<<endl;
system("pause");
return 0;
}
/*创建物体的重量及价值*/
void create_wuti(OBJECT T[], int t){
cout << "\n请输入物体的重量:";
for (int i = 0; i<t; i++)
cin >> T[i].w;
cout << "请输入物体的价值:";
for (int i = 0; i<t; i++)
cin >> T[i].p;
}
/*冒泡排序*/
void bubble_sort(OBJECT A[], int n){
OBJECT t;
for (int i = n - 1; i >0; i--){
for (int j = 0; j < i; j++){
if (A[j].v<A[j + 1].v){
t = A[j];
A[j] = A[j + 1];
A[j + 1] = t;
}
}
}
}
/*回溯法解0/1背包问题*/
float knapsack_back(OBJECT ob[ ], float m, int n,bool x[ ]){
float p_est; // 装入背包物体的估值
float w_est; // 装入背包物体的重量
float p_total; // 装入背包物体的价值上界
float w_cur; // 当前装入背包的物体的总重量
float p_cur; // 当前装入背包的物体的总价值
bool * y = new bool[ n+1 ];
for (int j=0; j<n; j++) { // 计算物体的价值重量比
ob[ j ].v = ob[ j ].p / ob[ j ].w;
y[ j ] = false; // 当前的解向量初始化
}
bubble_sort(ob,n); // 物体按价值重量比排序
int i,k = 0;
p_est=w_cur = p_cur = p_total = 0; // 初始化
y[n]=false;
while (k >= 0){
w_est = w_cur; p_est = p_cur;
for (i=k; i<n; i++){ // 计算最大估值
w_est = w_est + ob[ i ].w;
if (w_est < m)
p_est = p_est + ob[ i ].p;
else{
p_est+=((m-w_est+ob[ i ].w)/ob[ i ].w)*ob[i].p;
break;
}
}
if (p_est>p_total){ // 估计值大于上界
for (i=k; i<n; i++){
if (w_cur+ob[ i ].w <= m){ // 可装入第 i 个物体
w_cur = w_cur + ob[ i ].w;
p_cur = p_cur + ob[ i ].p;
y[ i ] = true;
}
else{
y[ i ] =false; break; // 不能装入第 i 个物体
}
}
if ( i >= n-1){ // n个物体已全部装入
if (p_cur > p_total){
p_total = p_cur; k = n; // 刷新当前上限
for (i=0; i<n; i++)
x[ i ] = y[ i ]; // 保存可行的解
}
}
else k = i + 1; // 继续装入其余物体
}
else{ // 估计价值小于当前上限,即if (p_est<=p_total)
while ((i >= 0)&&(y[ i ] == 0)) // 沿右分支回溯
i--; // 直到左分支结点
if (i<0) break; // 已到达根结点,算法结束
else{
w_cur = w_cur-ob[ i ].w; // 修改当前值50
p_cur = p_cur-ob[ i ].p;
y[ i ] =false;
k = i + 1; // 搜索右分支子树
}
}
}
delete y;
return p_total;
}
0 1背包问题
最新推荐文章于 2022-05-15 16:19:51 发布