基于回溯法的0-1背包问题

来源:互联网 发布:指南针炒股软件诈骗: 编辑:程序博客网 时间:2024/06/05 00:38

C++实现基于回溯法的0-1背包问题

#include<iostream>

using namespace std;

class Knap

{

friend int Knapsack(int p[], int w[], int c, int n);

public:

void print()

{

for (int m = 1; m <= n; m++)

{

cout << bestx[m] << " , ";

}

cout << endl;

};

private:

int Bound(int i);

void Backtrack(int i);

int c;//背包容量

int n; //物品数

int *w;//物品重量数组

int *p;//物品价值数组

int cw;//当前重量

int cp;//当前价值

int bestp;//当前最优值

int *bestx;//当前最优解

int *x;//当前解

};

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] / w[i] * cleft;

return b;

}

void Knap::Backtrack(int i)

{

if (i>n)

{

if (bestp<cp)

{

for (int j = 1; j <= n; j++)

bestx[j] = x[j];

bestp = cp;

}

return;

}

if (cw + w[i] <= c) //搜索左子树

{

x[i] = 1;

cw += w[i];

cp += p[i];

Backtrack(i + 1);

cw -= w[i];

cp -= p[i];

}

if (Bound(i + 1)>bestp)//搜索右子树

{

x[i] = 0;

Backtrack(i + 1);

}

}

class Object

{

friend int Knapsack(int p[], int w[], int c, int n);

public:

int operator<=(Object a)const

{

return (d >= a.d);

}

private:

int ID;

double d;

};

int Knapsack(int p[], int w[], int c, int n)

{

//为Knap::Backtrack初始化

int W = 0;

int P = 0;

int i = 1;

Object *Q = new Object[n];

for (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;//装入所有物品

//依物品单位重量排序

double f;

for (i = 0; i<n; i++)

for (int j = i; j<n; j++)

{

if (Q[i].d<Q[j].d)

{

f = Q[i].d;

Q[i].d = Q[j].d;

Q[j].d = f;

}

}

Knap K;

K.p = new int[n + 1];

K.w = new int[n + 1];

K.x = new int[n + 1];

K.bestx = new int[n + 1];

K.x[0] = 0;

K.bestx[0] = 0;

for (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);

cout << "  最优解为(bestx):";

  K.print();

delete[] Q;

delete[] K.w;

delete[] K.p;

return K.bestp;

}

void main()

{

int *p;

int *w;

int c = 0;

int n = 0;

int i = 0;

int k = 2;

while (1)

{

cout << endl;

cout << "  请输入背包容量(c):";

cin >> c;

cout << endl;

cout << "  请输入物品的个数(n):";

cin >> n;

cout << endl;

p = new int[n + 1];

w = new int[n + 1];

p[0] = 0;

w[0] = 0;

cout << "  请输入物品的价值(p)"<<endl;

for (i = 1; i <= n; i++)

{

cout << "      第" << i << "个物品的价值:";

cin >> p[i];

cout << endl;

}

cout << "  请输入物品的重量(w)"<<endl;

for (i = 1; i <= n; i++)

{

cout << "      第" << i << "个物品的重量:";

cin >> w[i];

cout << endl;

}

cout << "  请输入物品的价值(p):" ;

for (i = 1; i <= n; i++)

{

cout << "  ";

cout << p[i];

}

cout << endl;

cout << "  请输入物品的重量(w):";

for (i = 1; i <= n; i++)

{

cout << "  ";

cout << w[i];

}

cout << endl;

int num = Knapsack(p, w, c, n);

cout << "  最优值(bestp):"<<num;

cout << endl;

cout << "        1.重新开始" <<"     2.退出" << endl;

cout << "    请选择 1 或者 2 :";

cin >> k;

cout << endl;

if (k == 1)

{

continue;

}

else

{

break;

}

}

}


0 0
原创粉丝点击