| 标题: | 0-1背包问题 |
| 时 限: | 1000 ms |
| 内存限制: | 10000 K |
| 总时限: | 3000 ms |
| 描述: |
需对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高。 |
| 输入: |
多个测例,每个测例的输入占三行。第一行两个整数:n(n<=10)和c,第二行n个整数分别是w1到wn,第三行n个整数分别是p1到pn。n 和 c 都等于零标志输入结束。 |
| 输出: |
每个测例的输出占一行,输出一个整数,即最佳装载的总价值。 |
| 输入样例: |
1 2 |
| 输出样例: |
1 4 |
| 提示: | |
|
来源: |
回溯法
1 import java.sql.Array;
2 import java.util.ArrayList;
3 import java.util.Scanner;
4
5 public class Main {
6 static double c = 0;
7 static int n = 0;
8 static double[] w;
9 static double[] p;
10 static double cw;
11 static double cp;
12 static double bestp;
13
14 public static void main(String[] args) {
15 // TODO Auto-generated method stub
16
17 ArrayList<Integer> list=new ArrayList<Integer>();
18 Scanner myscanner = new Scanner(System.in);
19 n = myscanner.nextInt();
20 c = myscanner.nextDouble();
21
22 while (!(n == 0 && c == 0)) {
23 double[] pp = new double[n + 1];
24 double[] ww = new double[n + 1];
25 for (int i = 1; i <= n; i++) {
26 ww[i] = myscanner.nextDouble();
27 }
28 for (int i = 1; i <= n; i++) {
29 pp[i] = myscanner.nextDouble();
30 }
31 Knapsack(pp, ww, c);
32 //System.out.println("最大价值为:" + bestp);
33 list.add((int) bestp);
34 //System.out.println("请输入背包容量n的大小:");
35 n = myscanner.nextInt();
36 //System.out.println("请输入背包容量c的大小:");
37 c = myscanner.nextDouble();
38 }
39
40 for (int i = 0; i < list.size(); i++) {
41 System.out.println(list.get(i));
42 }
43 }
44
45 public static class Element implements Comparable {
46 int id;
47 double d;
48
49 private Element(int idd, double dd) {
50 id = idd;
51 d = dd;
52 }
53
54 public int compareTo(Object x) {
55 double xd = ((Element) x).d;
56 if (d < xd)
57 return -1;
58 if (d == xd)
59 return 0;
60 return 1;
61 }
62
63 public boolean equals(Object x) {
64 return d == ((Element) x).d;
65 }
66 }
67
68 public static double Knapsack(double[] pp, double[] ww, double cc) {
69 c = cc;
70 cw = 0.0;
71 cp = 0.0;
72 n = pp.length - 1;
73 bestp = 0.0;
74
75 Element[] q = new Element[n];
76
77 for (int i = 1; i <= n; i++) {
78 q[i - 1] = new Element(i, pp[i] / ww[i]);
79 }
80
81 for (int i = 0; i < n; i++) {
82 for (int j = 0; j < n - 1 - i; j++) {
83 if (q[j].d > q[j + 1].d) {
84 double temp = q[j].d;
85 q[j].d = q[j + 1].d;
86 q[j + 1].d = temp;
87 }
88 }
89 }
90
91 p = new double[n + 1];
92 w = new double[n + 1];
93 for (int i = 1; i <= n; i++) {
94 p[i] = pp[q[n - i].id];
95 w[i] = ww[q[n - i].id];
96 }
97
98 backtrack(1);
99 return bestp;
100 }
101
102 public static void backtrack(int i) {
103 if (i > n) {
104 bestp = cp;
105 return;
106 }
107
108 if (cw + w[i] <= c) {
109 cw += w[i];
110 cp += p[i];
111 backtrack(i + 1);
112 cw -= w[i];
113 cp -= p[i];
114 }
115
116 if (bound(i + 1) > bestp) {
117 backtrack(i + 1);
118 }
119 }
120
121 public static double bound(int i) {
122 double cleft = c - cw;
123 double bound = cp;
124 while (i <= n && w[i] <= cleft) {
125 cleft -= w[i];
126 bound += p[i];
127 i++;
128 }
129
130 if (i <= n) {
131 bound += p[i] * cleft / w[i];
132 }
133
134 return bound;
135 }
136 }
本文介绍了一种解决0-1背包问题的方法,通过回溯法实现最优装载方案,使得装载物品的价值最大化,同时不超过背包的容量限制。

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



