https://download.csdn.net/download/SQ_ZengYX/88620871
搜索与回溯
#include <iostream>
using namespace std;
#define N 100
int n;
double limitW;
double maxv;
int option[N];
int cop[N];
struct {
double weight;
double value;
} a[N];
void BackTrack(int i, double tw, double tv) {
// 不能超出重量限制
if (tw > limitW + 0.1)
return;
if (tv > maxv) {
for (int k = 0; k < n; ++k)
option[k] = cop[k];
maxv = tv;
}
// 选第i个物品
cop[i] = 1;
if (i < n)
BackTrack(i + 1, tw + a[i].weight, tv + a[i].value);
// 不选第i个物品
cop[i] = 0;
if (i < n)
BackTrack(i + 1, tw, tv);
}
int main() {
int k;
double w[N], v[N];
cout << "输入物品种数:" << endl;
cin >> n;
cout << "输入限制重量:" << endl;
cin >> limitW;
for (k = 0; k < n; ++k) {
cout << "依次输入第" << k + 1 << "个物品的重量和价值: " << endl;
cin >> w[k] >> v[k];
a[k].weight = w[k];
a[k].value = v[k];
}
maxv = 0.0;
for (k = 0; k < n; ++k)cop[k] = 0;
BackTrack(0, 0.0, 0.0);
cout << "所选物品为:" << endl;
for (k = 0; k < n; ++k)
if (option[k])
cout << k + 1 << "\t";
cout << endl << "总价值为:" << maxv << endl;
}
动态规划
#include<iostream>
using namespace std;
int weight[100], goods_value[100];//weight表示背包可容纳重量,godds_value表示物品价值
int Value[100][100];//价值数组
int ZeroOneBag(int goods_value[], int weight[], int Value[][100], int m, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (j < weight[i]) {
Value[i][j] = Value[i - 1][j];
} else if (Value[i - 1][j] >= (Value[i - 1][j - weight[i]] + goods_value[i])) {
Value[i][j] = Value[i - 1][j];
} else {
Value[i][j] = Value[i - 1][j - weight[i]] + goods_value[i];
}
}
}
return Value[m][n];
}
int main() {
int i = 0, m, n, value = 0;
cout << "请输入物品个数:" << endl;
cin >> m;
cout << "请输入背包容量:\n";
cin >> n;
for (i = 1; i <= m; i++) {
cout << "请输入物品" << i << endl;
cout << "重量: " << "价值: \n";
cin >> weight[i] >> goods_value[i];
}
value = ZeroOneBag(goods_value, weight, Value, m, n);
cout << "背包能容纳的最大价值为:" << value << endl;
cout << endl;
}
贪心
#include <iostream>
#include<algorithm>
using namespace std;
struct goodinfo {
float p; //物品效益
float w; //物品重量
float X; //物品该放的数量
int flag; //物品编号
bool operator<(goodinfo b) {
return p > b.p;
}//按物品效益,重量比值做升序排列
};//物品信息结构体
void bag(goodinfo goods[], float M, int n) {
float cu;
int i, j;
for (i = 1; i <= n; i++)
goods[i].X = 0;
cu = M; //背包剩余容量
for (i = 1; i < n; i++) {
if (goods[i].w > cu) //当该物品重量大与剩余容量跳出
continue;
goods[i].X = 1;
cu = cu - goods[i].w; //确定背包新的剩余容量
}
//按物品编号做降序排列
for (j = 2; j <= n; j++) {
goods[0] = goods[j];
i = j - 1;
while (goods[0].flag < goods[i].flag) {
goods[i + 1] = goods[i];
i--;
}
goods[i + 1] = goods[0];
}
cout << "最优解为:" << endl;
double ans = 0;
for (i = 1; i <= n; i++) {
cout << "第" << i << "件物品要放:";
cout << goods[i].X << endl;
ans += goods[i].p * goods[i].w * goods[i].X;
}
cout << "总价值为:" << ans << endl;
}
int main(void) {
cout << "|--------运用贪心法解背包问题---------|" << endl;
cout << "|-------------------------------------|" << endl;
int i, n;
float M;
cout << "请输入物品的总数量:";
cin >> n;
cout << "请输入背包的最大容量:";
cin >> M;
goodinfo goods[n + 1];
cout << endl;
for (i = 1; i <= n; i++) {
goods[i].flag = i;
cout << "请输入第" << i << "件物品的重量:";
cin >> goods[i].w;
cout << "请输入第" << i << "件物品的效益:";
cin >> goods[i].p;
goods[i].p = goods[i].p / goods[i].w; //得出物品的效益,重量比
cout << endl;
}
sort(goods + 1, goods + 1 + n);
bag(goods, M, n);
return 0;
}
模拟退火
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
void knapsackSa(int w[], int c[], int n, int M) { //n件物品,其重量和价值分别为w[i]和c[i],寻找将其装入容量为M的背包中物品的最大价值
int i, j, df, dm;
int *x = new int[n]; //定义解空间
for (i = 0; i < n; i++) { //初始化解为0
x[i] = 0;
}
int f = 0, m = 0;
for (i = 0; i < n; i++) {
f = f + c[i] * x[i]; //初始化总价值
m = m + w[i] * x[i]; //初始化总重量
}
float t0 = 500; //控制参数t的初值
float t = t0;
float a = 0.95f; //衰减函数的系数
float e = 0.00001f;
int L = 100 * n; // Mapkob 链长
while (t > e) { //停止准则
srand((unsigned)time(NULL));//初始化随机函数种子,srand((unsigned)time(NULL));是拿系统时间作为种子,由于时间是变化的,种子变化,可以产生不相同的随机数。
for (int k = 0; k < L; k++) {
i = rand() % n; //随机选取第i件物品
if (x[i] == 0) { //若i不在背包中
if (m + w[i] <= M) { //且加入总重量后不超过容量M,则直接放入背包中
x[i] = 1;
f = f + c[i];
m = m + w[i];
} else {
j = rand() % n; //随机取出物品j
while (x[j] == 0) {
j = rand() % n; //直到x[j]为1
}
df = c[i] - c[j];
dm = w[i] - w[j];
if (m + dm <= M) //加入总重量后不超过容量M
if (df > 0 || (exp(df / t) > (double)(rand() / (double)RAND_MAX))) { //价值差大于0或以exp(df/T)的接受概率接受新解
x[i] = 1;
x[j] = 0;
f = f + df;
m = m + dm;
}
}
} else {
j = rand() % n;
while (x[j] == 1) {
j = rand() % n;
}
df = c[j] - c[i];
dm = w[j] - w[i];
if (m + dm <= M)
if (df > 0 || (exp(df / t) > (double)(rand() / (double)RAND_MAX))) { //价值差大于0或以exp(df/T)的接受概率接受新解
x[i] = 0;
x[j] = 1;
f = f + df;
m = m + dm;
}
}
}
t = t * a; //衰减函数
}
cout << "该0/1背包问题的最优解为: ";
for (i = 0; i <= n - 1; i++) cout << x[i] << " ";
cout << endl << "最大总价值为:" << f << endl;
}
int main() {
int n, M;
//n件物品,其重量和价值分别为w[i]和c[i],寻找将其装入容量为M的背包中物品的最大价值
cout << "请输入物品件数n:" << endl;
cin >> n;
cout << "请输入背包容量M:" << endl;
cin >> M;
int *w = new int[n];
cout << "请依次输入物品重量和价值:" << endl;
int *c = new int[n];
for (int i = 0; i < n; i++) {
cin >> w[i] >> c[i];
}
knapsackSa(w, c, n, M);
return 0;
}
测试用例
8 8
2 5
3 8
2 6
4 9
5 10
4 7
3 8
5 14