最短経路の数え上げ

問題

ある都市の交差点Aから交差点Bへの最短経路の数を数えよ。この都市の道は下図のように碁盤の目状になっているとする






方針

最短の経路はすぐわかります。
結局、下にN回、右にM回移動することになります。


最短経路は結局、AとBを結ぶ四角形の中の道を、常識的(上に行ったり、右に行ったりしない)に結ぶ線の組み合わせの数ということになります。

この問題では、組み合わせの問題と考えた方が簡単に解を求められますが、ここでは動的計画法の問題として考えます。
動的計画法(どうてきけいかくほう、Dynamic Programming, DP)は、計算機科学の分野において、アルゴリズムの分類の1つである。対象となる問題を複数の部分問題に分割し、部分問題の計算結果を記録しながら解いていく手法を総称してこう呼ぶ。(Wikipedia) 

下図のような3点 (i, j), (i, j - 1), (i - 1, j) を考えた場合

  • (i, j - 1) から(i,  j) 
  • (i - 1, j) から(i, j)
へ移動する方法は一つしかないため
  • (i, j - 1)へ最短経路で到達する経路の数をP(i, j - 1)
  • (i - 1, j) へ最短経路で到達する経路の数をP(i - 1, j)
とした場合、(i, j)へ最短経路で到達する経路の数P(i, j)は

      a) 0 < i <= m, 0 < j <= nの場合
             P(i, j) = P(i, j - 1) + P(i - 1, j)
      b) i = 0またはj = 0の場合
             P(i, j) = 1

ということになります。

これをコードに落とすと、以下のようになります

コード

swift3

//
//  ShortestPathMatrix.swift
//  ShortestPathCounting
//
//  Created by 山崎真一郎 on 2017/02/04.
//  Copyright © 2017 山崎真一郎. All rights reserved.
//

import Foundation

class ShortestPathMatrix
{
    
    // 各ポイントへの最短経路数を
    // m_cNum * m_rNumの2次元配列と考える
    var m_elements: [[Int]] = []
    var m_cNum = 0
    var m_rNum = 0
    
    // 初期化処理
    init(rNum:Int, cNum:Int)
    {
        m_cNum = cNum
        m_rNum = rNum

        let row = Array(repeating: -1, count: m_cNum)
        m_elements = Array(repeating: row, count: m_rNum)
    }
    
    // 各ポイントの計算処理
    func calculate()
    {
        
        for row in 0...(m_rNum - 1)
        {
            for col in 0...(m_cNum - 1)
            {
                if (col == 0 || row == 0)
                {
                    m_elements[row][col] = 1
                }
                else
                {
                    m_elements[row][col] =
                        m_elements[row][col - 1] +
                        m_elements[row - 1][col]
                }
            }
        }
    }
    
    func printMatrix()
    {
        print(m_elements)
    }

}


var matrix = ShortestPathMatrix(rNum: 4, cNum: 5)
matrix.calculate()
matrix.printMatrix()




実行結果


[[1, 1, 1, 1, 1, 1],  [1, 2, 3, 4, 5, 6], [1, 3, 6, 10, 15, 21], [1, 4, 10, 20, 35, 56],  [1, 5, 15, 35, 70, 126]]


マトリックス上に結果を書くと、以下のようになります。