2 Коміти 1e502229e8 ... 8187c0f1f2

Автор SHA1 Опис Дата
  Guillaume Koenig 8187c0f1f2 Recursion to try a few different routes - score: 47.9M 7 роки тому
  Guillaume Koenig e25b00cee8 Prioq can now remove any element if its position is known 7 роки тому
1 змінених файлів з 75 додано та 39 видалено
  1. 75 39
      main.go

+ 75 - 39
main.go

@@ -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
 }