湘潭大学 算法设计与分析实验 回溯 动态规划 贪心 模拟退火解决背包问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SQ_ZYX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值