Don't Break the Nile 2

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)

}  

你可能感兴趣的:(break)