// @EXPECTED_RESULTS@: ACCEPTED,TIME_LIMIT_EXCEEDED /** * So Seeing a high timelimit and low boundaries means that a O(n^3) might be a possible valid algorithm. * I do a search for every possible plot, and precalculate which are the adjecant plots for every plot. * I also memorize if a decission once calculated. I think my algorithm is O(n^2 log n) due the use of sets to detect loops. * * Pitfall: Don't make the route from to the plot to the kiosk, it's the other way around. Then only example 1 works */ import kotlin.math.abs fun main() { val input = System.`in`.bufferedReader() val (m, n) = input.readLine().split(" ", limit = 2).map { it.toInt() } val size = m * n val map = Array(m) { input.readLine().split(" ", limit = n).map { it.toInt() }.toIntArray() } val options = mutableMapOf>() map.indices.forEach { x -> map[x].indices.forEach { y -> val plot = map[x][y] options[plot] = listOfNotNull( (x - 1).takeIf { it >= 0 }?.let { map[it][y] }, (x + 1).takeIf { it < m }?.let { map[it][y] }, (y - 1).takeIf { it >= 0 }?.let { map[x][it] }, (y + 1).takeIf { it < n }?.let { map[x][it] } ) } } val decissions = Array(size + 1) { IntArray(size + 1) } fun calculateNextStep(from: Int, to: Int): Int { if (decissions[from][to] != 0) return decissions[from][to] val directions = options[from]!!.withIndex().map { it.index to abs(to - it.value) }.sortedBy { it.second } val (best, value) = directions.first() if (directions.size > 1 && value == directions[1].second) { // closest plot voodoo val option1 = options[from]!![best] val option2 = options[from]!![directions[1].first] decissions[from][to] = when { abs(from - option1) < abs(from - option2) -> option1// option 1 is close else -> option2 } } else decissions[from][to] = options[from]!![best] return decissions[from][to] } var bestSpot = 0 var length = Int.MAX_VALUE for (start in 1..size) { var currentLength = 0 var plot = 1 while (plot <= size) { if (plot == start) { plot++ continue } val seen = BooleanArray(size+1) var l = 0 var next: Int = start do { seen[next] = true l++ next = calculateNextStep(next, plot) } while (next != plot && !seen[next]) if (next == plot) { currentLength = l.coerceAtLeast(currentLength) } else { break } plot++ } if (plot > size) { if (currentLength < length) { length = currentLength bestSpot = start } } } when (bestSpot) { 0 -> println("impossible") else -> println("$bestSpot $length") } }