|
@@ -2,6 +2,7 @@ package main
|
2
|
2
|
|
3
|
3
|
import (
|
4
|
4
|
"fmt"
|
|
5
|
+ "math/rand"
|
5
|
6
|
"os"
|
6
|
7
|
"sort"
|
7
|
8
|
)
|
|
@@ -65,6 +66,7 @@ func (rs ByEndtime) Less(i, j int) bool {
|
65
|
66
|
|
66
|
67
|
type Scheduler interface {
|
67
|
68
|
Add(*Car)
|
|
69
|
+ RemoveAtIndex(k int) *Car
|
68
|
70
|
Pop() *Car
|
69
|
71
|
}
|
70
|
72
|
|
|
@@ -76,7 +78,8 @@ type Car struct {
|
76
|
78
|
X int
|
77
|
79
|
Y int
|
78
|
80
|
|
79
|
|
- score int
|
|
81
|
+ score int
|
|
82
|
+ pqindex int // used for removal in prority queue
|
80
|
83
|
}
|
81
|
84
|
|
82
|
85
|
func (c *Car) Update(r *Ride) {
|
|
@@ -132,7 +135,23 @@ func max(a, b int) int {
|
132
|
135
|
}
|
133
|
136
|
}
|
134
|
137
|
|
135
|
|
-func Choose(c *Car) *Ride {
|
|
138
|
+var bestTotalScore int
|
|
139
|
+
|
|
140
|
+// invariant : when entering and leaving function,
|
|
141
|
+// Sched has the "same" heap. Same means successive
|
|
142
|
+// popped values will be the same (but the internal
|
|
143
|
+// ordering of nodes may be different)
|
|
144
|
+func Choose(cumulativeScore int, depth int) {
|
|
145
|
+ if cumulativeScore > bestTotalScore {
|
|
146
|
+ bestTotalScore = cumulativeScore
|
|
147
|
+ }
|
|
148
|
+ c := Sched.Pop()
|
|
149
|
+ if c == nil {
|
|
150
|
+ // Stop recursion, empty car list,
|
|
151
|
+ // could not match cars to rides
|
|
152
|
+ return
|
|
153
|
+ }
|
|
154
|
+
|
136
|
155
|
var bestRides []struct {
|
137
|
156
|
r *Ride
|
138
|
157
|
lenOfRide int
|
|
@@ -143,9 +162,9 @@ func Choose(c *Car) *Ride {
|
143
|
162
|
if r.used {
|
144
|
163
|
continue
|
145
|
164
|
}
|
146
|
|
- // if r.Length() > 6000 {
|
147
|
|
- // continue
|
148
|
|
- // }
|
|
165
|
+ if r.Length() > 6000 {
|
|
166
|
+ continue
|
|
167
|
+ }
|
149
|
168
|
if r.f < c.EarliestFinish(r) {
|
150
|
169
|
continue
|
151
|
170
|
}
|
|
@@ -161,7 +180,10 @@ func Choose(c *Car) *Ride {
|
161
|
180
|
}{r, lenOfRide, total})
|
162
|
181
|
// shitty sort-of-correct-but-quite-incorrect way
|
163
|
182
|
// of picking next best n rides
|
164
|
|
- n := 3
|
|
183
|
+ n := 1
|
|
184
|
+ if rand.Intn(max(1, int(N/5))) == 0 {
|
|
185
|
+ n = 3
|
|
186
|
+ }
|
165
|
187
|
if len(bestRides) > n {
|
166
|
188
|
bestRides = bestRides[len(bestRides)-n:]
|
167
|
189
|
}
|
|
@@ -171,31 +193,31 @@ func Choose(c *Car) *Ride {
|
171
|
193
|
// fmt.Printf("Picking %d %d -> %d %d\n", bestRide.a, bestRide.b, bestRide.x, bestRide.y)
|
172
|
194
|
// }
|
173
|
195
|
if len(bestRides) != 0 {
|
174
|
|
- // pick the not quite best ride...hey some
|
175
|
|
- // of the inputs already give a better score !
|
176
|
|
- return bestRides[0].r
|
177
|
|
- //return bestRides[len(bestRides)-1].r
|
178
|
|
- }
|
179
|
|
- return nil
|
180
|
|
-}
|
181
|
|
-
|
182
|
|
-func assign() bool {
|
183
|
|
- c := Sched.Pop()
|
184
|
|
- if c == nil {
|
185
|
|
- return false
|
186
|
|
- }
|
187
|
|
- r := Choose(c)
|
188
|
|
- if r == nil {
|
189
|
|
- return true
|
|
196
|
+ for _, br := range bestRides {
|
|
197
|
+ r := br.r
|
|
198
|
+ r.used = true
|
|
199
|
+ oldC := *c
|
|
200
|
+ c.Update(r)
|
|
201
|
+ Sched.Add(c)
|
|
202
|
+ // recursion 101
|
|
203
|
+ Choose(cumulativeScore+c.score-oldC.score, depth+1)
|
|
204
|
+ Sched.RemoveAtIndex(c.pqindex)
|
|
205
|
+ // pqindex is meaningless now but it's ok
|
|
206
|
+ // it will be fixed when c is added again
|
|
207
|
+ *c = oldC
|
|
208
|
+ r.used = false
|
|
209
|
+ }
|
|
210
|
+ } else {
|
|
211
|
+ // another car may still have other rides
|
|
212
|
+ Choose(cumulativeScore, depth)
|
190
|
213
|
}
|
191
|
|
- r.used = true
|
192
|
|
- c.Update(r)
|
|
214
|
+ // add back the one we popped at beginning of function
|
193
|
215
|
Sched.Add(c)
|
194
|
|
-
|
195
|
|
- return true
|
196
|
216
|
}
|
197
|
217
|
|
198
|
218
|
func solve() {
|
|
219
|
+ rand.Seed(1)
|
|
220
|
+
|
199
|
221
|
sort.Sort(ByEndtime(Rides))
|
200
|
222
|
|
201
|
223
|
Sched = &prioq{}
|
|
@@ -212,19 +234,17 @@ func solve() {
|
212
|
234
|
Sched.Add(c)
|
213
|
235
|
}
|
214
|
236
|
|
215
|
|
- for assign() {
|
216
|
|
- }
|
|
237
|
+ // start recursion
|
|
238
|
+ Choose(0, 0)
|
217
|
239
|
|
218
|
|
- totalScore := 0
|
219
|
240
|
for _, c := range Cars {
|
220
|
241
|
fmt.Fprintf(output, "%d", len(c.Rides))
|
221
|
242
|
for _, ri := range c.Rides {
|
222
|
243
|
fmt.Fprintf(output, " %d", ri)
|
223
|
244
|
}
|
224
|
245
|
fmt.Fprintf(output, "\n")
|
225
|
|
- totalScore += c.score
|
226
|
246
|
}
|
227
|
|
- fmt.Printf("%d\n", totalScore)
|
|
247
|
+ fmt.Printf("%d\n", bestTotalScore)
|
228
|
248
|
}
|
229
|
249
|
|
230
|
250
|
func main() {
|
|
@@ -295,31 +315,36 @@ type prioq struct {
|
295
|
315
|
|
296
|
316
|
func (pq *prioq) Add(car *Car) {
|
297
|
317
|
pq.bintree = append(pq.bintree, car)
|
|
318
|
+ pq.bintree[len(pq.bintree)-1].pqindex = len(pq.bintree) - 1
|
298
|
319
|
|
299
|
320
|
// Rebalance tree to respect invariant
|
300
|
321
|
var i = len(pq.bintree) - 1
|
301
|
322
|
var p = (i - 1) / 2
|
302
|
323
|
for p >= 0 && pq.bintree[p].Arrival > pq.bintree[i].Arrival {
|
303
|
324
|
pq.bintree[p], pq.bintree[i] = pq.bintree[i], pq.bintree[p]
|
|
325
|
+ pq.bintree[p].pqindex = p
|
|
326
|
+ pq.bintree[i].pqindex = i
|
304
|
327
|
i = p
|
305
|
328
|
p = (i - 1) / 2
|
306
|
329
|
}
|
307
|
330
|
}
|
308
|
331
|
|
309
|
|
-func (pq *prioq) Pop() *Car {
|
|
332
|
+func (pq *prioq) RemoveAtIndex(k int) *Car {
|
310
|
333
|
if len(pq.bintree) == 0 {
|
311
|
334
|
return nil
|
312
|
335
|
}
|
313
|
336
|
|
314
|
|
- if len(pq.bintree) == 1 {
|
315
|
|
- elem := pq.bintree[0]
|
316
|
|
- pq.bintree = pq.bintree[:0]
|
|
337
|
+ if k == len(pq.bintree)-1 {
|
|
338
|
+ elem := pq.bintree[k]
|
|
339
|
+ pq.bintree = pq.bintree[:k]
|
317
|
340
|
return elem
|
318
|
341
|
}
|
319
|
342
|
|
320
|
|
- elem := pq.bintree[0]
|
321
|
|
- // Put last element at root
|
322
|
|
- pq.bintree[0] = pq.bintree[len(pq.bintree)-1]
|
|
343
|
+ pq.bintree[k].pqindex = -1
|
|
344
|
+ elem := pq.bintree[k]
|
|
345
|
+ // Put last element at hole
|
|
346
|
+ pq.bintree[k] = pq.bintree[len(pq.bintree)-1]
|
|
347
|
+ pq.bintree[k].pqindex = k
|
323
|
348
|
// Remove last element
|
324
|
349
|
pq.bintree = pq.bintree[:len(pq.bintree)-1]
|
325
|
350
|
|
|
@@ -330,7 +355,8 @@ func (pq *prioq) Pop() *Car {
|
330
|
355
|
|
331
|
356
|
// Rebalance tree to respect invariant
|
332
|
357
|
len := len(pq.bintree)
|
333
|
|
- i, left, right := 0, 0, 0
|
|
358
|
+ i := k
|
|
359
|
+ left, right := 0, 0
|
334
|
360
|
for {
|
335
|
361
|
left = 2*i + 1
|
336
|
362
|
right = 2*i + 2
|
|
@@ -340,6 +366,8 @@ func (pq *prioq) Pop() *Car {
|
340
|
366
|
break // Inferior to both children
|
341
|
367
|
} else {
|
342
|
368
|
pq.bintree[i], pq.bintree[left] = pq.bintree[left], pq.bintree[i]
|
|
369
|
+ pq.bintree[i].pqindex = i
|
|
370
|
+ pq.bintree[left].pqindex = left
|
343
|
371
|
i = left
|
344
|
372
|
}
|
345
|
373
|
} else {
|
|
@@ -347,6 +375,8 @@ func (pq *prioq) Pop() *Car {
|
347
|
375
|
break // Inferior to both children
|
348
|
376
|
} else {
|
349
|
377
|
pq.bintree[i], pq.bintree[right] = pq.bintree[right], pq.bintree[i]
|
|
378
|
+ pq.bintree[i].pqindex = i
|
|
379
|
+ pq.bintree[right].pqindex = right
|
350
|
380
|
i = right
|
351
|
381
|
}
|
352
|
382
|
}
|
|
@@ -355,6 +385,8 @@ func (pq *prioq) Pop() *Car {
|
355
|
385
|
break // Inferior to only child
|
356
|
386
|
}
|
357
|
387
|
pq.bintree[i], pq.bintree[left] = pq.bintree[left], pq.bintree[i]
|
|
388
|
+ pq.bintree[i].pqindex = i
|
|
389
|
+ pq.bintree[left].pqindex = left
|
358
|
390
|
i = left
|
359
|
391
|
} else { // No child
|
360
|
392
|
break
|
|
@@ -365,6 +397,10 @@ func (pq *prioq) Pop() *Car {
|
365
|
397
|
return elem
|
366
|
398
|
}
|
367
|
399
|
|
|
400
|
+func (pq *prioq) Pop() *Car {
|
|
401
|
+ return pq.RemoveAtIndex(0)
|
|
402
|
+}
|
|
403
|
+
|
368
|
404
|
func (pq *prioq) empty() bool {
|
369
|
405
|
return len(pq.bintree) == 0
|
370
|
406
|
}
|