5-33 0-1背包问题
问题描述
试设计一个用回溯法搜索子集空间树的函数。该函数的参数包括结点可行性判定函数和上界函数等必要的函数,并将此函数用于解 0-1 背包问题。
0-1 背包问题描述如下:给定 n 种物品和一个背包。物品 i 的重量是 wiwi ,其价值为vivi ,背包的容量为 C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品 i 只有 2 种选择,即装入背包或不装入背包。不能将物品 i 装入背包多次,也不能只装入部分的物品 i。
0-1 背包问题形式化描述:给定C>0C>0,wi>0wi>0,vi>0vi>0,1≤i≤n1≤i≤n,要求 n 元 0-1 向量(x1,x2,...,xn)(x1,x2,...,xn), xi∈{0,1}xi∈{0,1},1≤i≤n1≤i≤n,使得 ∑i=1nwixi≤C∑i=1nwixi≤C, 而且∑i=1nvixi∑i=1nvixi 达到最大。
数据输入:
第一行有 2 个正整数 n 和 c。n 是物品数,c 是背包的容 量。接下来的 1 行中有 n 个正整数,表示物品的价值。第 3 行中有 n 个正整数,表示物品的 重量。
Java
package Chapter5HuiSuFa;
import java.util.Scanner;
public class BeiBao01 {
private static int n,c;
private static int[] x,bestx,w,p;
private static int cw,cp,bestp;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
bestp = 0;
cw = 0;
cp = 0;
n = input.nextInt();
c = input.nextInt();
w = new int[n+1];
p = new int[n+1];
x = new int[n+1];
bestx = new int[n+1];
for(int i=1; i<=n; i++)
p[i] = input.nextInt();
for(int i=1; i<=n; i++)
w[i] = input.nextInt();
backtrack(1);
output();
}
}
private static void backtrack(int t){
if(t > n) record();
else
for(int i=0; i<=1; i++){
x[t] = i;
if(constraint(t) && bound(t)){
change(t);
backtrack(t+1);
restore(t);
}
}
}
private static void record(){
if(cp > bestp){
bestp = cp;
for(int i=1; i<=n; i++)
bestx[i] = x[i];
}
}
private static boolean constraint(int t){
if(x[t]==0 || x[t]==1 && cw+w[t]<=c) return true;
else return false;
}
private static boolean bound(int t){
if(x[t]==1 || x[t]==0 && upbound(t+1)>bestp) return true;
else return false;
}
private static int upbound(int k){
int cleft = c-cw;
int b = cp;
while (k<=n && w[k]<=cleft){
cleft -= w[k];
b += p[k];
k++;
}
if(k <= n)
b += p[k]*cleft/w[k];
return b;
}
private static void change(int t){
if(x[t] == 1){
cw += w[t];
cp += p[t];
}
}
private static void restore(int t){
if(x[t] == 1){
cw -= w[t];
cp -= p[t];
}
}
private static void output(){
System.out.println(bestp);
for(int i=1; i<=n; i++)
System.out.print(bestx[i]+" ");
}
}
Input & Output
5 10
6 3 5 4 6
2 2 6 5 4
15
1 1 0 0 1
5 10
5 3 6 6 4
6 2 2 4 5
15
0 1 1 1 0
5 10
4 5 3 6 6
5 6 2 2 4
15
0 0 1 1 1
5 10
3 6 6 4 5
2 2 4 5 6
15
1 1 1 0 0
Reference
王晓东《计算机算法设计与分析》(第3版)P188

本文介绍了如何运用回溯法来解决经典的0-1背包问题。0-1背包问题要求在有限的背包容量下,选择物品以最大化总价值,每种物品只能选一次。文章提供了解决这个问题的Java实现,并给出了数据输入和输出的说明。
1991

被折叠的 条评论
为什么被折叠?



