|
@@ -154,92 +154,125 @@ func save() {
|
154
|
154
|
fmt.Printf("%d\n", bestTotalScore)
|
155
|
155
|
}
|
156
|
156
|
|
157
|
|
-// invariant : when entering and leaving function,
|
158
|
|
-// Sched has the "same" heap. Same means successive
|
159
|
|
-// popped values will be the same (but the internal
|
160
|
|
-// ordering of nodes may be different)
|
161
|
|
-func Choose(cumulativeScore int, depth int) {
|
162
|
|
- if cumulativeScore > bestTotalScore {
|
163
|
|
- bestTotalScore = cumulativeScore
|
164
|
|
- save()
|
165
|
|
- }
|
166
|
|
- c := Sched.Pop()
|
167
|
|
- if c == nil {
|
168
|
|
- // Stop recursion, empty car list,
|
169
|
|
- // could not match cars to rides
|
170
|
|
- return
|
171
|
|
- }
|
|
157
|
+func (c *Car) AssignRideRecur(r *Ride, cumulativeScore int, depth int, fromDepth int) (int, bool) {
|
|
158
|
+ r.used = true
|
|
159
|
+ oldC := *c
|
|
160
|
+ c.Update(r)
|
|
161
|
+ Sched.Add(c)
|
|
162
|
+ // recursion 101
|
|
163
|
+ rdepth, fix := Choose(cumulativeScore+c.score-oldC.score, depth+1, fromDepth)
|
|
164
|
+ Sched.RemoveAtIndex(c.pqindex)
|
|
165
|
+ // pqindex is meaningless now but it's ok
|
|
166
|
+ // it will be fixed when c is added again
|
|
167
|
+ *c = oldC
|
|
168
|
+ r.used = false
|
|
169
|
+ return rdepth, fix
|
|
170
|
+}
|
|
171
|
+
|
|
172
|
+func (c *Car) CanPick(r *Ride) bool {
|
|
173
|
+ return !r.used && r.Length() <= 8000 && r.f >= c.EarliestFinish(r)
|
|
174
|
+}
|
|
175
|
+
|
|
176
|
+func (c *Car) pickBestRide() *Ride {
|
|
177
|
+ var bestRide *Ride
|
|
178
|
+ var bestRideTotal int
|
|
179
|
+ var bestRideLen int
|
172
|
180
|
|
173
|
|
- var bestRides []struct {
|
174
|
|
- r *Ride
|
175
|
|
- lenOfRide int
|
176
|
|
- total int
|
177
|
|
- }
|
178
|
|
- // fmt.Printf("car %d\n", c.ID)
|
179
|
181
|
for _, r := range Rides {
|
180
|
|
- if r.used {
|
|
182
|
+ if !c.CanPick(r) {
|
181
|
183
|
continue
|
182
|
184
|
}
|
183
|
|
- if r.Length() > 8000 {
|
|
185
|
+
|
|
186
|
+ lenOfRide := r.length()
|
|
187
|
+ total := max(c.distanceTo(r.a, r.b), r.s-c.Arrival) + lenOfRide
|
|
188
|
+ if bestRide == nil || lenOfRide*bestRideTotal > total*bestRideLen {
|
|
189
|
+ bestRide = r
|
|
190
|
+ bestRideLen = lenOfRide
|
|
191
|
+ bestRideTotal = total
|
|
192
|
+ }
|
|
193
|
+ }
|
|
194
|
+
|
|
195
|
+ return bestRide
|
|
196
|
+}
|
|
197
|
+
|
|
198
|
+func (c *Car) pickRandomRide() *Ride {
|
|
199
|
+ count := 0
|
|
200
|
+ for _, r := range Rides {
|
|
201
|
+ if !c.CanPick(r) {
|
184
|
202
|
continue
|
185
|
203
|
}
|
186
|
|
- if r.f < c.EarliestFinish(r) {
|
|
204
|
+ count++
|
|
205
|
+ }
|
|
206
|
+ i := rand.Intn(count)
|
|
207
|
+ for _, r := range Rides {
|
|
208
|
+ if !c.CanPick(r) {
|
187
|
209
|
continue
|
188
|
210
|
}
|
189
|
|
- // fmt.Printf("%d %d -> %d %d\n", r.a, r.b, r.x, r.y)
|
190
|
|
- lenOfRide := r.length()
|
191
|
|
- total := max(c.distanceTo(r.a, r.b), r.s-c.Arrival) + lenOfRide
|
192
|
|
- // fmt.Printf("%d/%d\n", lenOfRide, total)
|
193
|
|
- if len(bestRides) == 0 || lenOfRide*bestRides[len(bestRides)-1].total > total*bestRides[len(bestRides)-1].lenOfRide {
|
194
|
|
- bestRides = append(bestRides, struct {
|
195
|
|
- r *Ride
|
196
|
|
- lenOfRide int
|
197
|
|
- total int
|
198
|
|
- }{r, lenOfRide, total})
|
199
|
|
- // shitty sort-of-correct-but-quite-incorrect way
|
200
|
|
- // of picking next best n rides
|
201
|
|
- n := 1
|
202
|
|
- if rand.Intn(max(1, int(N/20))) == 0 {
|
203
|
|
- n = 2
|
204
|
|
- }
|
205
|
|
- if len(bestRides) > n {
|
206
|
|
- bestRides = bestRides[len(bestRides)-n:]
|
207
|
|
- }
|
|
211
|
+ if i == 0 {
|
|
212
|
+ return r
|
208
|
213
|
}
|
|
214
|
+ i = i - 1
|
209
|
215
|
}
|
210
|
|
- // if bestRide != nil {
|
211
|
|
- // fmt.Printf("Picking %d %d -> %d %d\n", bestRide.a, bestRide.b, bestRide.x, bestRide.y)
|
212
|
|
- // }
|
213
|
|
- if len(bestRides) != 0 {
|
214
|
|
- if (len(bestRides)) >= 2 {
|
215
|
|
- // if big difference in length, try both
|
216
|
|
- // otherwise pick best according to score
|
217
|
|
- d := abs(bestRides[0].r.length() - bestRides[1].r.length())
|
218
|
|
- if d < 1000 {
|
219
|
|
- bestRides = bestRides[1:]
|
220
|
|
- }
|
|
216
|
+ return nil
|
|
217
|
+}
|
221
|
218
|
|
|
219
|
+// invariant : when entering and leaving function,
|
|
220
|
+// Sched has the "same" heap. Same means successive
|
|
221
|
+// popped values will be the same (but the internal
|
|
222
|
+// ordering of nodes may be different)
|
|
223
|
+// Return value (a,b) :
|
|
224
|
+// - rdepth >= 0 return back to that depth
|
|
225
|
+// - rdepth < 0 completely unwind stack and finish
|
|
226
|
+// - fix == false try to make a change at depth `rdepth'
|
|
227
|
+// - fix == true change back, use "optimal" ride again
|
|
228
|
+func Choose(cumulativeScore int, depth int, fromDepth int) (int, bool) {
|
|
229
|
+ c := Sched.Pop()
|
|
230
|
+ if c == nil {
|
|
231
|
+ // At this point we have a complete configuration
|
|
232
|
+ fmt.Printf("score obtained: %d depth: %d\n", cumulativeScore, depth)
|
|
233
|
+ // INVESTIGATE HERE : why do we have different scores ???
|
|
234
|
+ // when we're only asking to fix 22 down in the stack
|
|
235
|
+ return 8270, true
|
|
236
|
+ if cumulativeScore >= bestTotalScore {
|
|
237
|
+ bestTotalScore = cumulativeScore
|
|
238
|
+ // Go back to random depth and make a new change
|
|
239
|
+ return rand.Intn(depth), false
|
|
240
|
+ } else {
|
|
241
|
+ // Go back to fix change that lowered our score
|
|
242
|
+ return fromDepth, true
|
222
|
243
|
}
|
223
|
|
- for _, br := range bestRides {
|
224
|
|
- r := br.r
|
225
|
|
- r.used = true
|
226
|
|
- oldC := *c
|
227
|
|
- c.Update(r)
|
228
|
|
- Sched.Add(c)
|
229
|
|
- // recursion 101
|
230
|
|
- Choose(cumulativeScore+c.score-oldC.score, depth+1)
|
231
|
|
- Sched.RemoveAtIndex(c.pqindex)
|
232
|
|
- // pqindex is meaningless now but it's ok
|
233
|
|
- // it will be fixed when c is added again
|
234
|
|
- *c = oldC
|
235
|
|
- r.used = false
|
|
244
|
+ }
|
|
245
|
+
|
|
246
|
+ var rdepth int
|
|
247
|
+ var fix bool
|
|
248
|
+ r := c.pickBestRide()
|
|
249
|
+ // if depth >= 252 && depth <= 258 {
|
|
250
|
+ // fmt.Printf("yo picking id %d score %d c=%+v\n", r.ID, cumulativeScore, c)
|
|
251
|
+ // }
|
|
252
|
+ if r != nil {
|
|
253
|
+ rdepth, fix = c.AssignRideRecur(r, cumulativeScore, depth, fromDepth)
|
|
254
|
+ // if depth == reverse depth, make a change
|
|
255
|
+ // and go back up the stack
|
|
256
|
+ for depth == rdepth {
|
|
257
|
+ var r *Ride
|
|
258
|
+ if fix {
|
|
259
|
+ r = c.pickBestRide()
|
|
260
|
+ fmt.Printf("pickBestRide id %d depth %d\n", r.ID, depth)
|
|
261
|
+ } else {
|
|
262
|
+ r = c.pickRandomRide()
|
|
263
|
+ fmt.Printf("pickRandomRide id %d depth %d\n", r.ID, depth)
|
|
264
|
+ }
|
|
265
|
+ // note fromDepth reset to depth
|
|
266
|
+ rdepth, fix = c.AssignRideRecur(r, cumulativeScore, depth, depth)
|
236
|
267
|
}
|
237
|
268
|
} else {
|
238
|
269
|
// another car may still have other rides
|
239
|
|
- Choose(cumulativeScore, depth)
|
|
270
|
+ rdepth, fix = Choose(cumulativeScore, depth, fromDepth)
|
240
|
271
|
}
|
241
|
272
|
// add back the one we popped at beginning of function
|
242
|
273
|
Sched.Add(c)
|
|
274
|
+ // go back down the stack
|
|
275
|
+ return rdepth, fix
|
243
|
276
|
}
|
244
|
277
|
|
245
|
278
|
func solve() {
|
|
@@ -262,7 +295,7 @@ func solve() {
|
262
|
295
|
}
|
263
|
296
|
|
264
|
297
|
// start recursion
|
265
|
|
- Choose(0, 0)
|
|
298
|
+ Choose(0, 0, 0)
|
266
|
299
|
}
|
267
|
300
|
|
268
|
301
|
func main() {
|