`

0 1背包问题

阅读更多
1. 问题描述

   给定n种物品和一背包。物品i的重量是wi,其价值为pi,背包的容量为c。问:应该如何选择装入背包的物品,使得装入
背包中物品的总价值最大?

2. 问题分析

   在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。该问题是子集选取问题。因此解空间可用子集书
来表示。

   在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索。
否则将右子树剪去。

   设r是当前剩余物品价值总和;cp是当前价值;bestp是当前最优价值。当cp+r <= bestp时,可剪去右子树。

   计算右子树中解的上界的更好的方法是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分
而装满背包。由此得到的价值是右子树中解的上界。

3. 举例子说明:

  n = 4;
  c = 7;
  pi = [9, 10, 7, 4];
  wi = [3, 5, 2 ,1];
  单位重量价值分别为[3, 2, 3.5, 4];

  则以物品单位重量价值的递减顺序装入物品。先装入物品4, 然后装入物品3, 再装入物品1, 则背包容量剩余为:7-(1+2+3)=1.
最后只能只能装入1/5 = 0.2的物品2。由此得到一个解为x=[1,0.2,1,1],其相应的价值为22.因此,对于这个实例,最优值不超过22.

4. Java实现

package com.maozj.suanfa;

import java.util.Arrays;

/**
 * 0 1背包问题回溯算法
 * 
 * @since jdk1.5以上
 * @author 毛正吉
 * @version 1.0
 * @date 2010.05.22
 */
public class ZeroOneQuestion {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		double[] pp = { 0, 9, 10, 7, 4 };
		double[] ww = { 0, 3, 5, 2, 1 };
		double cc = 7.0;

		double result = zeroOneQuestion(pp, ww, cc);
		System.out.println("result=" + result);
	}

	private static class Element implements Comparable {
		int id; // 物品编号
		double dv; // 单位重量价值

		private Element(int _id, double _dv) {
			id = _id;
			dv = _dv;
		}

		public int compareTo(Object o) {
			int res = 0;
			double d = ((Element) o).dv;

			if (dv < d) {
				res = -1;
			} else if (dv == d) {
				res = 0;
			} else {
				res = 1;
			}
			return res;
		}

		public boolean equals(Object o) {
			return (dv == ((Element) o).dv);
		}

		public String toString() {
			return "id=" + id + ", dv=" + dv;
		}
	}

	static double c; // 背包容量
	static int n; // 物品数
	static double[] w; // 物品重量数组
	static double[] p; // 物品价值数组
	static double cw; // 当前重量
	static double cp; // 当前价值
	static double bestp;// 当前最优价值

	public static double zeroOneQuestion(double[] pp, double[] ww, double cc) {
		c = cc;
		n = pp.length - 1;
		cw = 0.0;
		cp = 0.0;
		bestp = 0.0;

		// q为单位重量价值数组
		Element[] q = new Element[n];
		Element[] qq = new Element[n];

		// 初始化q[0, n-1]
		for (int i = 1; i <= n; i++) {
			q[i - 1] = new Element(i, pp[i] / ww[i]);
		}

		// 将各物品依单位重量价值从大到小排序
		Arrays.sort(q);
		for (int i = 0; i < n; i++) {
			qq[i] = q[n - i - 1];
		}

		for (int i = 0; i < n; i++) {
			System.out.println(qq[i]);
		}
		System.out.println();
		System.out.println("################################");

		p = new double[n + 1];
		w = new double[n + 1];
		for (int i = 1; i <= n; i++) {
			p[i] = pp[qq[i-1].id];
			w[i] = ww[qq[i-1].id];
		}

		for (int i = 1; i <= n; i++) {
			System.out.print(p[i] + " ");
		}
		System.out.println();
		for (int i = 1; i <= n; i++) {
			System.out.print(w[i] + " ");
		}
		System.out.println();

		// 回溯搜索
		backtrack(1);

		return bestp;
	}

	private static void backtrack(int i) {
		if (i > n) {
			bestp = cp;
			return;
		}

		// 搜索子树
		if (cw + w[i] <= c) {
			// 进入左子树
			cw += w[i];
			cp += p[i];

			backtrack(i + 1);

			cw -= w[i];
			cp -= p[i];
		}

		if (bound(i + 1) > bestp) {
			// 进入右子树
			backtrack(i + 1);
		}
	}

	/**
	 * 计算上界
	 * 
	 * @param i
	 * @return
	 */
	private static double bound(int i) {
		double cleft = c - cw; // 剩余容量
		double bound = cp;

		// 以物品单位重量价值递减顺序装入物品
		while ((i <= n) && (w[i] <= cleft)) {
			cleft -= w[i];
			bound += p[i];
			i++;
		}

		// 装满背包
		if (i <= n) {
			bound += p[i] / w[i] * cleft;
		}
		return bound;
	}
}
0
1
分享到:
评论

相关推荐

    用 C语言编写的求“0 1背包问题”的代码

    0 1背包问题是一个经典的计算机科学中的组合优化问题,它源于实际生活中的资源分配和决策问题。在这个问题中,我们有n个物品,每个物品都有一个重量w[i]和一个价值p[i],同时还有一个容量为m的背包。目标是选择物品...

    0 1 背包问题 分支界限 回溯+剪枝

    问题描述:给定一个容量为C的背包及n个重量为wi,价值为p1的物品,要求把物品装入背包,是背包的价值最大,此类问题为背包...解决方法:0/1背包问题有多种解决方法,本实验用动态规划,回溯,分支界限三种方法进行解题

    数据集目录,其中 包含 0 1 背包问题的测试数据.rar

    这个特定的数据集,名为“包含 0 1 背包问题的测试数据.rar”,是一个针对0-1背包问题的经典数据集。0-1背包问题是一个优化问题,它在运筹学、计算机科学和经济学等多个领域都有广泛的应用。 0-1背包问题的基本概念...

    0-1背包问题(动态规划)

    利用动态规划方法求解经典0-1背包问题,仅供参考,欢迎指正

    利用遗传算法解0 1背包问题.doc

    利用遗传算法解0 1背包问题.doc

    python 0 1背包问题 原理 代码实现

    python 0-1背包问题原理和代码实现 背包问题是一种经典的组合优化问题,可以描述为:给定一组物品,每种物品都有自己的重量和价值,在限定的总重量内,我们如何选择,才能使得物品的总价值最高。python作为一种灵活...

    0-1背包问题

    0-1背包问题是一种经典的计算机科学中的组合优化问题,它源于实际生活中的资源分配问题,例如在有限的容量下选择最有价值的物品进行携带。在这个问题中,我们有一组物品,每种物品都有一个重量和一个价值,目标是...

    C# 0/1背包问题过程演示源码

    0/1背包问题是一种经典的计算机科学优化问题,广泛应用于资源分配、任务选择等场景。它在C#编程中可以通过动态规划来解决。本压缩包包含的"01背包问题过程演示"源码,提供了一个直观的实现示例,旨在帮助初学者理解...

    0-1背包_0-1背包问题_背包算法_背包_

    0-1背包问题是一种经典的组合优化问题,在计算机科学和运筹学中有着广泛的应用。它源于实际生活中的装箱问题,比如如何在限定的重量限制下,选择物品以获得最大价值。在这里,我们主要探讨0-1背包问题的定义、算法...

    C++实现回溯算法 0 1 背包算法

    背包问题可以分为 0 1 背包问题和无限制背包问题两种。 2. 回溯算法的基本思想 回溯算法是解决背包问题的一种常用方法。回溯算法的基本思想是通过递归和回溯来搜索所有可能的解,并选择其中的最优解。 3. C++ 语言...

    C++ 0-1背包问题源代码

    在计算机科学中,0-1背包问题是一个经典的优化问题,属于NP完全问题。该问题描述如下:假设有一个背包,其最大承重为W,现在有n个物品,每个物品都有自己的重量wi和价值vi。对于每个物品,我们只能选择放或不放,不...

    0_1背包问题

    在提供的压缩文件"0 1背包问题_回溯法"中,可能包含了具体的C语言源代码示例,通过阅读和理解这段代码,你可以更深入地了解如何实际应用回溯法解决01背包问题。学习并理解这个算法有助于提升你的编程能力和解决复杂...

    利用回溯法解0-1背包问题讲解

    利用回溯法解0-1背包问题讲解 利用回溯法解0-1背包问题是子集选取问题,0-1背包问题是NP难题,回溯法可以很好地解决背包问题,以期得到最优解。 回溯法概念: * 回溯法是一个既带有系统性又带有跳跃性的搜索算法...

    0-1背包问题(java实现代码)

    根据提示信息输入要测试的数据文件的编号(1-5),数据文件中第一行分别为背包容量和物品个数,第二行为物品重量,第三行为物品价值,用" "分隔(如:1 2 3)。输入数据文件的编号后程序开始运行,依次输出背包总...

    0-1背包问题(回溯算法)

    0-1背包问题是一种经典的组合优化问题,在计算机科学和运筹学中有着广泛的应用。它描述的是这样的场景:你有一个背包,其容量有限,而有一系列物品,每个物品都有自己的重量和价值。你的目标是在不超过背包容量的...

    动态规划法和回溯法求0-1背包问题

    ### 动态规划法与回溯法解决0-1背包问题 #### 一、实验目的与背景 0-1背包问题是一种经典的组合优化问题,在实际应用中有着广泛的用途,例如资源分配、投资组合等问题都可以抽象成背包问题的形式。本实验旨在通过...

    动态规划解决0-1背包问题

    动态规划是一种有效的算法设计策略,尤其适用于解决具有重叠子问题和最优子结构的问题,而0-1背包问题就是这种策略的一个典型应用。0-1背包问题是一个经典的组合优化问题,它源自实际生活中的资源分配问题,比如在...

    0-1背包问题-算法简洁易懂

    0-1背包问题算法简洁易懂 0-1背包问题简介 0-1背包问题是算法设计中的一种经典问题。它是一个组合优化问题,属于NP-hard问题。问题的描述是:给定一组物品,每个物品都有一个价值和一个重量,要求在不超过背包容量...

    动态规划求解0-1背包问题的改进算法完整解释

    动态规划求解0-1背包问题的改进算法完整解释 在计算机算法设计与分析中,动态规划法是解决背包问题的常用方法之一。所谓背包问题,是指在有限的背包容量下,如何选择物品来达到最大价值的问题。在本文中,我们将对...

    NSGA2解决0-1背包问题_nsga2_cookci7_0-1NSGA2_用NSGA2解决背包问题_

    0-1背包问题是一种经典的组合优化问题,在计算机科学和运筹学中有着广泛的应用。它描述的是这样的场景:有一组物品,每个物品有自己的价值和重量,且每件物品只能选择0次或1次(不能部分选取)。目标是在不超过背包...

Global site tag (gtag.js) - Google Analytics