Shortest Sum Path(Option Pricing: Trinomial Tree)

Problem: You have a n x n grid:

2

4

3

1

3

2

1

4

4

2

3

1

1

2

3

4

 

You have to start at the bottom row (highlighted red) and make your way to the top row (highlighted green). You can only move straight up or diagonally left or right.

You have to find the shortest path (based on the sums in each cell) and print the path. For example, in the above grid the shortest path is:

1 -> 2 -> 1 -> 1

The sum is 5.

 

 

import scala.collection.mutable.ArrayBuffer

object ShortestPaths extends App {

  def getPath(mat: Array[Array[Int]]): ArrayBuffer[List[Int]] = {
    if (mat.length <= 0)
      return null
    val lineLen: Int = mat(0).length
    var preOptPaths = new Array[(Int, ArrayBuffer[List[Int]])](lineLen)
    for ((line, row) <- mat.view.zipWithIndex) {
      if (row == 0) {
        for ((num, col) <- line.view.zipWithIndex) {
          val line0: Array[Int] = mat(0)
          preOptPaths(col) = (line0(col), ArrayBuffer(List(line0(col))))
          print(preOptPaths(col))
        }
      }
      else {
        val currentOptPaths = new Array[(Int, ArrayBuffer[List[Int]])](lineLen)
        for ((num, col) <- line.view.zipWithIndex) {
          var minColSum = Int.MaxValue
          var minCols: ArrayBuffer[Int] = null
          for {c <- (col - 1) to (col + 1)
               if c >= 0 && c <= lineLen - 1
               cSum = preOptPaths(c)._1
          } {
            if (cSum < minColSum) {
              minColSum = cSum
              minCols = ArrayBuffer(c)
            }
            else if (cSum == minColSum) {
              minCols += c
            }
          }
          val currentVal = line(col)
          currentOptPaths(col) = (currentVal + minColSum, minCols.flatMap(preOptPaths(_)._2).map(currentVal :: _))
          print(currentOptPaths(col))
        }
        preOptPaths = currentOptPaths
      }
      println()
    }
    var minSum = Int.MaxValue
    var bestPaths: ArrayBuffer[List[Int]] = null
    for (path <- preOptPaths) {
      if (path._1 < minSum) {
        minSum = path._1
        bestPaths = ArrayBuffer(path._2: _*)
      }
      else if (path._1 == minSum) {
        bestPaths ++= path._2
      }
    }
    bestPaths
  }

  /* TEST

  println(getPath(Array(
    Array(2, 4, 3, 1),
    Array(3, 2, 1, 4),
    Array(4, 2, 3, 1),
    Array(1, 2, 3, 4)
  )))

  println("==========")
  println(getPath(Array(
    Array(2, 1, 3, 1),
    Array(3, 2, 1, 4),
    Array(4, 2, 3, 1),
    Array(1, 2, 3, 2)
  )))
  */

}

 

 

posted @ 2016-03-12 09:12  新一代的天皇巨星  阅读(306)  评论(0)    收藏  举报