模拟退火算法解决背包问题

232 阅读1分钟

题目be like: image.png 做这个实验的时候看课本上的例子并没有考虑到重量的问题,拿去问了同学他反问我如果随机取值一直取不到重量小于c的值要怎么办,是不是包含了太多的不确定性,我觉得这是个值得深思问题,最后他的解法是容错但不加入最优解,这题不考虑c的话最优解是17,考虑的话是14。

于是有两种思路:一种就是非要取到总重量小于c的三个物品(我选择的方法),一种的话我想就是记录17这个值,随后看看是否小于c,不小于则继续取值。

const c = 8
const w = [2, 3, 5, 1, 4]
const v = [2, 5, 8, 3, 6]
var T = 10

var arr = new Array(n).fill(0)
//初始化,随机选择三个下标,把这三个下标的对应值改成1
var init = function(add) {
	let initial = []

	while (add < 3) {
		let rand = Math.floor(5 * Math.random());
		if (initial.indexOf(rand) == -1) {
			initial.push(rand);
			arr[rand] = 1
			add++;
		}
	}
	return arr
}
var calc = function(arr) {
	let sum = 0
	for (let j = 0; j < n; j++) {
		if (arr[j] == 1) {
			sum += v[j]
		}
	}
	return sum
}
/* var change = function() {
	//随机取两个下标,如果两个下标的值不相等就交换
	let rand1 = 0
	let rand2 = 0
	let t = 0
	while (rand1 == rand2 || arr[rand1] == arr[rand2]) {
		rand1 = Math.floor(5 * Math.random());
		rand2 = Math.floor(5 * Math.random());
	}
	t = arr[rand1]
	arr[rand1] = arr[rand2]
	arr[rand2] = t
	//计算重量有没有超
	let weight = 0
	for (let j = 0; j < n; j++) {
		if (arr[j] == 1) {
			weight += w[j]
		}
	}
	return arr
} */
var calaWeight=function(){
	const change=()=>{
		let rand1 = 0
		let rand2 = 0
		let t = 0
		while (rand1 == rand2 || arr[rand1] == arr[rand2]) {
			rand1 = Math.floor(5 * Math.random());
			rand2 = Math.floor(5 * Math.random());
		}
		t = arr[rand1]
		arr[rand1] = arr[rand2]
		arr[rand2] = t
		//计算重量有没有超
		let weight = 0
		for (let j = 0; j < n; j++) {
			if (arr[j] == 1) {
				weight += w[j]
			}
		}
		return weight
	}
	let temp=change()
	while(temp>c){
		temp=change()
	}
	return arr
}
var best = calc(init(0))
while (T > 0 && best !=14) {
	let b = 0
	while (b < 3) {
		//计算新解
		let calcSum = calc(calaWeight())
		//如果新解小于原解,那就用exp判断要不要接受
		if (calcSum < best) {
			//计算接受概率
			let t = Math.exp((calcSum - best) / T)
			if (Math.random() < t) {
				best = calcSum
			}
		} else {
			//如果适应值大的话就直接赋值
			best=calcSum
		}
		b++
		console.log(best)
	}
	T--
}
console.log('....',best)

ps:中间注释的部分就是不考虑超重的写法

结果如下:

image.png