2 Commitit 1e502229e8 ... 8187c0f1f2

Tekijä SHA1 Viesti Päivämäärä
  Guillaume Koenig 8187c0f1f2 Recursion to try a few different routes - score: 47.9M 7 vuotta sitten
  Guillaume Koenig e25b00cee8 Prioq can now remove any element if its position is known 7 vuotta sitten
1 muutettua tiedostoa jossa 75 lisäystä ja 39 poistoa
  1. 75 39
      main.go

+ 75 - 39
main.go

@@ -2,6 +2,7 @@ package main
2
 
2
 
3
 import (
3
 import (
4
 	"fmt"
4
 	"fmt"
5
+	"math/rand"
5
 	"os"
6
 	"os"
6
 	"sort"
7
 	"sort"
7
 )
8
 )
@@ -65,6 +66,7 @@ func (rs ByEndtime) Less(i, j int) bool {
65
 
66
 
66
 type Scheduler interface {
67
 type Scheduler interface {
67
 	Add(*Car)
68
 	Add(*Car)
69
+	RemoveAtIndex(k int) *Car
68
 	Pop() *Car
70
 	Pop() *Car
69
 }
71
 }
70
 
72
 
@@ -76,7 +78,8 @@ type Car struct {
76
 	X       int
78
 	X       int
77
 	Y       int
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
 func (c *Car) Update(r *Ride) {
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
 	var bestRides []struct {
155
 	var bestRides []struct {
137
 		r         *Ride
156
 		r         *Ride
138
 		lenOfRide int
157
 		lenOfRide int
@@ -143,9 +162,9 @@ func Choose(c *Car) *Ride {
143
 		if r.used {
162
 		if r.used {
144
 			continue
163
 			continue
145
 		}
164
 		}
146
-		// if r.Length() > 6000 {
147
-		// 	continue
148
-		// }
165
+		if r.Length() > 6000 {
166
+			continue
167
+		}
149
 		if r.f < c.EarliestFinish(r) {
168
 		if r.f < c.EarliestFinish(r) {
150
 			continue
169
 			continue
151
 		}
170
 		}
@@ -161,7 +180,10 @@ func Choose(c *Car) *Ride {
161
 			}{r, lenOfRide, total})
180
 			}{r, lenOfRide, total})
162
 			// shitty sort-of-correct-but-quite-incorrect way
181
 			// shitty sort-of-correct-but-quite-incorrect way
163
 			// of picking next best n rides
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
 			if len(bestRides) > n {
187
 			if len(bestRides) > n {
166
 				bestRides = bestRides[len(bestRides)-n:]
188
 				bestRides = bestRides[len(bestRides)-n:]
167
 			}
189
 			}
@@ -171,31 +193,31 @@ func Choose(c *Car) *Ride {
171
 	// 	fmt.Printf("Picking %d %d -> %d %d\n", bestRide.a, bestRide.b, bestRide.x, bestRide.y)
193
 	// 	fmt.Printf("Picking %d %d -> %d %d\n", bestRide.a, bestRide.b, bestRide.x, bestRide.y)
172
 	// }
194
 	// }
173
 	if len(bestRides) != 0 {
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
 	Sched.Add(c)
215
 	Sched.Add(c)
194
-
195
-	return true
196
 }
216
 }
197
 
217
 
198
 func solve() {
218
 func solve() {
219
+	rand.Seed(1)
220
+
199
 	sort.Sort(ByEndtime(Rides))
221
 	sort.Sort(ByEndtime(Rides))
200
 
222
 
201
 	Sched = &prioq{}
223
 	Sched = &prioq{}
@@ -212,19 +234,17 @@ func solve() {
212
 		Sched.Add(c)
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
 	for _, c := range Cars {
240
 	for _, c := range Cars {
220
 		fmt.Fprintf(output, "%d", len(c.Rides))
241
 		fmt.Fprintf(output, "%d", len(c.Rides))
221
 		for _, ri := range c.Rides {
242
 		for _, ri := range c.Rides {
222
 			fmt.Fprintf(output, " %d", ri)
243
 			fmt.Fprintf(output, " %d", ri)
223
 		}
244
 		}
224
 		fmt.Fprintf(output, "\n")
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
 func main() {
250
 func main() {
@@ -295,31 +315,36 @@ type prioq struct {
295
 
315
 
296
 func (pq *prioq) Add(car *Car) {
316
 func (pq *prioq) Add(car *Car) {
297
 	pq.bintree = append(pq.bintree, car)
317
 	pq.bintree = append(pq.bintree, car)
318
+	pq.bintree[len(pq.bintree)-1].pqindex = len(pq.bintree) - 1
298
 
319
 
299
 	// Rebalance tree to respect invariant
320
 	// Rebalance tree to respect invariant
300
 	var i = len(pq.bintree) - 1
321
 	var i = len(pq.bintree) - 1
301
 	var p = (i - 1) / 2
322
 	var p = (i - 1) / 2
302
 	for p >= 0 && pq.bintree[p].Arrival > pq.bintree[i].Arrival {
323
 	for p >= 0 && pq.bintree[p].Arrival > pq.bintree[i].Arrival {
303
 		pq.bintree[p], pq.bintree[i] = pq.bintree[i], pq.bintree[p]
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
 		i = p
327
 		i = p
305
 		p = (i - 1) / 2
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
 	if len(pq.bintree) == 0 {
333
 	if len(pq.bintree) == 0 {
311
 		return nil
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
 		return elem
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
 	// Remove last element
348
 	// Remove last element
324
 	pq.bintree = pq.bintree[:len(pq.bintree)-1]
349
 	pq.bintree = pq.bintree[:len(pq.bintree)-1]
325
 
350
 
@@ -330,7 +355,8 @@ func (pq *prioq) Pop() *Car {
330
 
355
 
331
 	// Rebalance tree to respect invariant
356
 	// Rebalance tree to respect invariant
332
 	len := len(pq.bintree)
357
 	len := len(pq.bintree)
333
-	i, left, right := 0, 0, 0
358
+	i := k
359
+	left, right := 0, 0
334
 	for {
360
 	for {
335
 		left = 2*i + 1
361
 		left = 2*i + 1
336
 		right = 2*i + 2
362
 		right = 2*i + 2
@@ -340,6 +366,8 @@ func (pq *prioq) Pop() *Car {
340
 					break // Inferior to both children
366
 					break // Inferior to both children
341
 				} else {
367
 				} else {
342
 					pq.bintree[i], pq.bintree[left] = pq.bintree[left], pq.bintree[i]
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
 					i = left
371
 					i = left
344
 				}
372
 				}
345
 			} else {
373
 			} else {
@@ -347,6 +375,8 @@ func (pq *prioq) Pop() *Car {
347
 					break // Inferior to both children
375
 					break // Inferior to both children
348
 				} else {
376
 				} else {
349
 					pq.bintree[i], pq.bintree[right] = pq.bintree[right], pq.bintree[i]
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
 					i = right
380
 					i = right
351
 				}
381
 				}
352
 			}
382
 			}
@@ -355,6 +385,8 @@ func (pq *prioq) Pop() *Car {
355
 				break // Inferior to only child
385
 				break // Inferior to only child
356
 			}
386
 			}
357
 			pq.bintree[i], pq.bintree[left] = pq.bintree[left], pq.bintree[i]
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
 			i = left
390
 			i = left
359
 		} else { // No child
391
 		} else { // No child
360
 			break
392
 			break
@@ -365,6 +397,10 @@ func (pq *prioq) Pop() *Car {
365
 	return elem
397
 	return elem
366
 }
398
 }
367
 
399
 
400
+func (pq *prioq) Pop() *Car {
401
+	return pq.RemoveAtIndex(0)
402
+}
403
+
368
 func (pq *prioq) empty() bool {
404
 func (pq *prioq) empty() bool {
369
 	return len(pq.bintree) == 0
405
 	return len(pq.bintree) == 0
370
 }
406
 }