package codejam.year2004.round2
import scala.io.Source
import scala.collection.mutable.Queue
object DontBreakTheNile2 extends App {
val file = "src/main/scala/codejam/year2004/round2/C-large-practice.in"
val lines = Source.fromFile(file).getLines()
val T = lines.next().toInt
def process(t: Int): Unit =
if (t <= T) {
val line = lines.next().split("\\s+").map(_.toInt)
val w = line(0)
val h = line(1)
val b = line(2)
trait Block {
def dist(that: Block): Int
}
case class Building(x0: Int, y0: Int, x1: Int, y1: Int) extends Block {
private def distX(that: Building) =
if (x0 <= that.x1 && that.x0 <= x1) 0
else if (x1 < that.x0) that.x0 - x1 - 1
else x0 - that.x1 - 1
private def distY(that: Building) =
if (y0 <= that.y1 && that.y0 <= y1) 0
else if (y1 < that.y0) that.y0 - y1 - 1
else y0 - that.y1 - 1
def dist(that: Block) = that match {
case LeftBank => x0
case RightBank => w - 1 - x1
case b: Building => distX(b) max distY(b)
}
}
case object LeftBank extends Block {
def dist(that: Block) = that match {
case b: Building => b.dist(this)
case RightBank => w
}
}
case object RightBank extends Block {
def dist(that: Block) = that match {
case b: Building => b.dist(this)
case LeftBank => w
}
}
def readBlock(i: Int, blocks: Map[Int, Block]): Map[Int, Block] =
if (i == b + 2) blocks
else if (i == b + 1) readBlock(i + 1, blocks + (i -> RightBank))
else if (i == b) readBlock(i + 1, blocks + (i -> LeftBank))
else {
val cord = lines.next().split("\\s+").map(_.toInt)
readBlock(i + 1, blocks + (i -> Building(cord(0), cord(1), cord(2), cord(3))))
}
val blocks = readBlock(0, Map.empty)
val grid = Array.fill(b + 2)(Array.fill(b + 2)(0))
for {
i <- 0 until b + 2
a = blocks(i)
j <- (i + 1) until b + 2
b = blocks(j)
d = a.dist(b)
} {
grid(i)(j) = d
grid(j)(i) = d
}
def min(xs: Array[Int], i: Int, m: Int, checked: Set[Int]): Int =
if (i >= xs.length) m
else {
if (checked.contains(i)) min(xs, i + 1, m, checked)
else if (m < 0 || xs(m) > xs(i)) min(xs, i + 1, i, checked)
else min(xs, i + 1, m, checked)
}
def bfs(dist: Array[Int], checked: Set[Int]): Int = {
val i = min(dist, 0, -1, checked)
if (i == b + 1) dist(i)
else {
val v = dist(i)
for {
j <- 0 until b + 2
if (j != i && !checked.contains(j))
} {
if (v + grid(i)(j) < dist(j)) {
dist(j) = v + grid(i)(j)
}
}
bfs(dist, checked + i)
}
}
val dist = Array.fill(b + 2)(w)
dist(b) = 0
val minCut = bfs(dist, Set.empty)
println(s"Case #$t: $minCut")
process(t + 1)
}
process(1)
}
Don't Break the Nile 2
最新推荐文章于 2024-08-02 22:53:22 发布