#include<bits/stdc++.h>
using namespace std;
class Knap
{
friend int Knapsack(int *, int *, int, int);
private:
int Bound(int i);
void Backtrack(int i);
int c;
int n;
int *w;
int *p;
int *number;
bool *select;
int cw;
int cp;
int bestp;
};
void Knap::Backtrack(int i)
{
static int k = 1;
if(i > n)
{
bestp = cp;
cout<<"第"<<k++<<"次到达叶节点,得到的最优价值为:"<<bestp<<endl;
cout<<"此次物品选择情况为:"<<endl;
for(int i=1; i<=n; i++)
{
if(select[i]==true) cout<<"选择物品"<<number[i]<<": 重量"<<w[i]<<" 价值"<<p[i]<<endl;
}
return ;
}
if(cw + w[i] <= c)
{
cout<<"进入左子树深入一层,将到达第"<<i+1<<"层"<<endl;
cw += w[i];
cp += p[i];
select[i] = true;
Backtrack(i+1);
cout<<"从左子树回溯一层,将到达第"<<i<<"层"<<endl;
select[i] = false;
cw -= w[i];
cp -= p[i];
}
else cout<<"此时: cw:"<<cw<<" w[i]:"<<w[i]<<" 则cw+w[i]>c,不满足约束条件,无法继续向左,尝试向右"<<endl;
if(Bound(i+1) > bestp)
{
cout<<"进入右子树深入一层,将到达第"<<i+1<<"层"<<endl;
Backtrack(i+1);
cout<<"从右子树回溯一层,将到达第"<<i<<"层"<<endl;
}
else cout<<"尝试向右,计算得到Bound[i+1]:"<<Bound(i+1)<<" Bound(i+1)<=bestp,不满足限界条件,直接剪枝"<<endl;
}
int Knap::Bound(int i)
{
int cleft = c - cw;
int b = cp;
while(i<=n && w[i]<=cleft)
{
cleft -= w[i];
b += p[i];
i++;
}
if(i<=n)
b += p[i]*cleft/w[i];
return b;
}
class Object
{
friend int Knapsack(int *, int *, int, int);
public:
int ID;
float d;
};
bool cmp(Object a, Object b)
{
return a.d >= b.d;
}
int Knapsack(int *p, int *w, int c, int n)
{
int W = 0;
int P = 0;
Object *Q = new Object[n+1];
for(int i=1; i<=n; i++)
{
Q[i-1].ID = i;
Q[i-1].d = 1.0*p[i]/w[i];
P += p[i];
W += w[i];
}
if(W <= c)
return P;
sort(Q, Q+n, cmp);
int *temp_Number = new int[n+1];
cout<<"排序后的数组为:";
for(int i=1; i<=n; i++)
{
temp_Number[i] = Q[i-1].ID;
cout<<Q[i-1].ID<<" ";
}
cout<<endl;
Knap K;
K.number = new int[n+1];
K.number = temp_Number;
K.select = new bool[n+1];
for(int i=0; i<=n; i++) K.select[i] = false;
K.p = new int[n+1];
K.w = new int[n+1];
for(int i=1; i<=n; i++)
{
K.p[i] = p[Q[i-1].ID];
K.w[i] = w[Q[i-1].ID];
}
K.cp = 0;
K.cw = 0;
K.c = c;
K.n = n;
K.bestp = 0;
K.Backtrack(1);
delete[] Q;
delete[] K.w;
delete[] K.p;
return K.bestp;
}
int main()
{
cout<<"请输入背包总容量:";
int c;
while(cin>>c && c)
{
cout<<"请输入物品总件数:";
int n;
cin>>n;
cout<<"请输入每件物品的重量以及价值"<<endl;
int *w = new int[n+1];
int *p = new int[n+1];
for(int i=1; i<=n; i++)
{
cout<<"物品"<<i<<":";
cin>>w[i]>>p[i];
}
int ans = Knapsack(p, w, c, n);
cout<<"最优装载价值为:"<<ans<<endl;
delete[] w;
delete[] p;
cout<<"请输入背包总容量:";
}
system("pause");
return 0;
}