1
- import java .io .*;
2
- import java .util .List ;
3
-
4
-
1
+ import java .io .BufferedReader ;
2
+ import java .io .FileReader ;
3
+ import java .io .IOException ;
5
4
import java .util .ArrayList ;
5
+ import java .util .Arrays ;
6
+ import java .util .HashMap ;
7
+ import java .util .List ;
8
+ import java .util .Map ;
6
9
7
10
/**
8
- * The class <code>Solver</code> is an implementation of a greedy algorithm to solve the knapsack problem.
11
+ * The class <code>Solver</code> is an implementation of solve framework to solve the knapsack problem.
9
12
*
10
13
*/
11
14
public class Solver {
@@ -67,36 +70,93 @@ public static void solve(String[] args) throws IOException {
67
70
weights [i -1 ] = Integer .parseInt (parts [1 ]);
68
71
}
69
72
73
+ Item [] a = new Item [items ];
74
+ for (int i =0 ; i <items ; ++i ){
75
+ a [i ] = new Item ();
76
+ a [i ].value = values [i ];
77
+ a [i ].weight = weights [i ];
78
+ a [i ].idx = i ;
79
+ }
80
+ Arrays .sort (a );
81
+ // for(int i=0 ; i< items ; ++i)
82
+ // System.out.println(a[i].value + " " + a[i].weight);
83
+ for (int i =0 ; i <items ; ++i ){
84
+ values [i ] = a [i ].value ;
85
+ weights [i ] = a [i ].weight ;
86
+ }
70
87
// a trivial greedy algorithm for filling the knapsack
71
88
// it takes items in-order until the knapsack is full
72
89
73
- KnapsackSolver solver = new DPSolver ();
74
- solver .solve (items ,capacity ,values ,weights );
75
-
90
+ // KnapsackSolver solver = (long) items*capacity > DPSolver.MAX_SOLVE_SPACE?
91
+ // new LDSSolver() : new DPSolver();
92
+
93
+ KnapsackSolver solver = new LDSSolver ();
94
+
95
+ Map <String ,Object > ans = solver .solve (items ,capacity ,values ,weights );
96
+ int [] taken = new int [items ];
97
+ int [] ansIdx = (int [])ans .get ("taken" );
98
+ for (int i =0 ; i <items ; ++i )taken [a [i ].idx ] = ansIdx [i ];
99
+ ans .put ("taken" , taken );
100
+ output (ans );
76
101
}
77
- public static void output (int value ,int opt ,int [] taken ) {
102
+ public static void output (Map <String ,Object > ans ) {
103
+ int value = (int )ans .get ("value" );
104
+ int opt = (int )ans .get ("opt" );
105
+ int [] taken = (int [])ans .get ("taken" );
78
106
System .out .println (value +" " +opt );
79
107
int items = taken .length ;
80
108
for (int i =0 ; i < items ; i ++){
81
109
System .out .print (taken [i ]+" " );
82
110
}
83
111
System .out .println ("" );
84
112
}
113
+ public static Map <String ,Object > constructAns (int value ,int opt ,int [] taken ) {
114
+ Map <String ,Object > ans = new HashMap <>();
115
+ ans .put ("value" , value );
116
+ ans .put ("opt" , opt );
117
+ ans .put ("taken" , taken );
118
+
119
+ return ans ;
120
+ }
121
+
122
+
123
+ }
124
+
125
+ /**
126
+ * Item
127
+ */
128
+ class Item implements Comparable <Item >{
129
+ int value ,weight ;
130
+ int idx ;
131
+ public int compareTo (Item o ){
132
+ return value - o .value ;
133
+ }
85
134
}
86
135
87
136
137
+ /**
138
+ * This interface <code> KnapsackSolver </code> provides a general interface for solving knapsack problem
139
+ */
88
140
interface KnapsackSolver {
89
- public void solve (int n ,int K ,int [] values ,int [] weights );
141
+ /**
142
+ * this method is a interface that given items {@code n}, capcity {@code K}, and value {@code values} with {@code weights}
143
+ * @param n number of items
144
+ * @param K capcity of bag
145
+ * @param values a int array {@code values[i]} represented the value of ith item
146
+ * @param weights a int array {@code weights[i]} represented the weight of ith item
147
+ */
148
+ public Map <String ,Object > solve (int n ,int K ,int [] values ,int [] weights );
90
149
}
91
150
151
+ /**
152
+ * this a danamic programing solver for knapsack problem
153
+ */
154
+
92
155
class DPSolver implements KnapsackSolver {
93
- private static final int MAX_SOLVE_SPACE = 100000000 ;
94
- public void solve (int n ,int K ,int [] values ,int [] weights ){
95
- if (n * K > MAX_SOLVE_SPACE )
96
- System .err .printf ("need memory %d, but MAX_SOLVE_SPACE is %d\n " ,n *K ,MAX_SOLVE_SPACE );
156
+ public static final int MAX_SOLVE_SPACE = 100000000 ;
157
+ public Map <String ,Object > solve (int n ,int K ,int [] values ,int [] weights ){
97
158
int maxv ;
98
- int opt =1 ;
99
- int [] token = new int [n ];
159
+ int [] taken = new int [n ];
100
160
int [][] dp = new int [K +1 ][n ];
101
161
for (int k = 1 ; k <= K ; ++k ){
102
162
dp [k ][0 ] = (k >=weights [0 ]? values [0 ] : 0 );
@@ -111,11 +171,83 @@ public void solve(int n,int K,int[] values,int[] weights){
111
171
int k = K ;
112
172
for (int j = n -1 ; j >0 ; --j ){
113
173
if (k >= weights [j ] && dp [k ][j ] == dp [k -weights [j ]][j -1 ] +values [j ]){
114
- token [j ] =1 ;
174
+ taken [j ] =1 ;
115
175
k -=weights [j ];
116
176
}
117
177
}
118
- if (dp [k ][0 ] !=0 )token [0 ] =1 ;
119
- Solver .output (maxv , opt , token );
178
+ if (dp [k ][0 ] !=0 )taken [0 ] =1 ;
179
+ return Solver .constructAns (maxv , 1 , taken );
120
180
}
121
181
}
182
+
183
+ /**
184
+ * LDSSolver,limited discrepancy search solver for knapsack problem
185
+ */
186
+ class LDSSolver implements KnapsackSolver {
187
+
188
+ /**
189
+ * just for least paras in member methods
190
+ */
191
+ private int [] vals ;
192
+ private int [] weights ;
193
+ private int ans ;
194
+ private int [] bestVec ; // the final tacken vector
195
+ private static final long elapsedTime = 1000000000L ;//10 s
196
+ private long startTime ;
197
+ public Map <String ,Object > solve (int n ,int K ,int [] v ,int [] w ) {
198
+ vals = v ;
199
+ weights = w ;
200
+ KnapsackSolver initSolver = new DPSolver ();
201
+ int cap = Math .min (DPSolver .MAX_SOLVE_SPACE /n ,K );
202
+ Map <String ,Object > initAns = initSolver .solve (n , cap , v , w );
203
+ if ((long )n *K <= DPSolver .MAX_SOLVE_SPACE ) return initAns ;
204
+ ans = (int )initAns .get ("value" );
205
+ // System.out.println("dp ans= " + ans);
206
+ bestVec = (int [])initAns .get ("taken" );
207
+ int tks = 0 ;
208
+ for (int i =0 ; i < n ; ++i )tks += bestVec [i ];
209
+
210
+
211
+ int [] tmpw = weights .clone ();
212
+ Arrays .sort (tmpw );
213
+ int min = 0 ;
214
+ int s =0 ;
215
+ for ( ; s +weights [min ] <= K && min <n ; s += weights [min ],min ++ );
216
+ for (int i =min ; i < n ; ++i )s +=weights [i ];
217
+ for (int mis = n -min ; mis <=n -tks +5 ; ++mis ){
218
+ startTime = System .nanoTime ();
219
+ lds (0 , s ,K ,mis , n -1 , new int [n ]);
220
+ }
221
+
222
+ return Solver .constructAns (ans , 0 , bestVec );
223
+ }
224
+ /**
225
+ * ths limited discrepancy search method, you can find detail at this paper {@link https://ai.dmi.unibas.ch/research/reading_group/harvey-ginsberg-ijcai1995.pdf}
226
+ * @param best the value of cur node
227
+ * @param estimate the best value of cur node
228
+ * @param leftCap the left capcity
229
+ * @param mistake the right branch of search tree
230
+ * @param i the ith item
231
+ * @return
232
+ */
233
+ private void lds (int best ,int estimate ,int leftCap ,int mistake ,int i ,int [] taken ) {
234
+ if (estimate < ans ) return ;// prun the branch
235
+ if (mistake >i +1 )return ;
236
+ if (leftCap <0 )return ;
237
+ if (i < 0 || leftCap -weights [i ]<0 || System .nanoTime () - startTime > elapsedTime ){
238
+ if (best > ans ){
239
+ ans = best ;
240
+ for (int j =taken .length -1 ; j >i ; --j )bestVec [j ] = taken [j ];
241
+ for (int j =i ; j >=0 ; --j )bestVec [j ] =0 ;
242
+ }
243
+ return ;
244
+ }
245
+ // not take the ith item, mistake -1
246
+ if (mistake >0 ){
247
+ taken [i ] =0 ;
248
+ lds (best , estimate , leftCap , mistake -1 , i -1 , taken );
249
+ }
250
+ taken [i ] =1 ;
251
+ lds (best + vals [i ], estimate - vals [i ],leftCap -weights [i ], mistake , i -1 , taken );
252
+ }
253
+ }
0 commit comments