github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/dp/matrix_min_dist_test.go (about)

     1  package dp
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  )
     7  
     8  /*
     9  矩阵最短距离
    10  
    11  {
    12  	{1,3,5,9}
    13  	{2,1,3,4}
    14  	{5,2,6,7}
    15  	{6,8,4,3}
    16  }
    17  
    18  求解左上到右下点最短距离, 每一步只能往右 或 下走
    19  
    20  思路: 到 (i,j) 状态的最小值,只能由(i-1,j) 或 (i,j-1) 两个状态转变过来
    21  minDis[i][j]= m[i][j] + min(m[i][j-1], m[i-1][j])
    22  */
    23  
    24  // 回溯法的写法 i表示纵轴, j 表示横轴
    25  func minDistBacktracing(i, j, dis int, m [][]int, ret *int) {
    26  	maxY := len(m) - 1
    27  	maxX := len(m[0]) - 1
    28  	if i == maxY && j == maxX {
    29  		if *ret > dis+m[maxY][maxX] {
    30  			*ret = dis + m[maxY][maxX]
    31  		}
    32  		return
    33  	}
    34  	if j < maxX { // 向左走
    35  		minDistBacktracing(i, j+1, dis+m[i][j], m, ret)
    36  	}
    37  	if i < maxY { // 向下走
    38  		minDistBacktracing(i+1, j, dis+m[i][j], m, ret)
    39  	}
    40  }
    41  
    42  // 动态规划的方式
    43  func minDistDp(m [][]int) int {
    44  	yl := len(m)
    45  	xl := len(m[0])
    46  
    47  	dp := make([][]int, yl)
    48  	for i := range dp {
    49  		dp[i] = make([]int, xl)
    50  
    51  	}
    52  	dp[0][0] = m[0][0]
    53  	// 设置初始首行和首列的状态
    54  	for i := 1; i < yl; i++ { //首列
    55  		dp[i][0] = dp[i-1][0] + m[i][0]
    56  	}
    57  	for j := 1; j < xl; j++ { // 首行
    58  		dp[0][j] = dp[0][j-1] + m[0][j]
    59  	}
    60  
    61  	for i := 1; i < yl; i++ {
    62  		for j := 1; j < xl; j++ {
    63  			dp[i][j] = m[i][j] + min(dp[i][j-1], dp[i-1][j])
    64  		}
    65  	}
    66  	// 倒推路径
    67  	printPath(yl-1, xl-1, m, dp)
    68  	return dp[yl-1][xl-1]
    69  }
    70  
    71  func printPath(y int, x int, m [][]int, dp [][]int) {
    72  	fmt.Printf("(%v,%v,%v)", y, x, m[y][x])
    73  	for y > 0 && x > 0 {
    74  		switch dp[y][x] - m[y][x] {
    75  		case dp[y-1][x]:
    76  			y--
    77  		case dp[y][x-1]:
    78  			x--
    79  		}
    80  		fmt.Printf("<-(%v,%v,%v)", y, x, m[y][x])
    81  	}
    82  	fmt.Printf("<-(%v,%v,%v)\n", 0, 0, m[0][0])
    83  }
    84  
    85  func min(a, b int) int {
    86  	if a > b {
    87  		return b
    88  	}
    89  	return a
    90  }
    91  
    92  func TestMinDis(t *testing.T) {
    93  	m := [][]int{
    94  		{1, 3, 5, 9},
    95  		{2, 1, 3, 4},
    96  		{5, 2, 6, 7},
    97  		{6, 8, 4, 3},
    98  		//{6, 8, 4, 23},
    99  	}
   100  
   101  	ret := 0x7fffffff
   102  	minDistBacktracing(0, 0, 0, m, &ret)
   103  	t.Log(ret)
   104  
   105  	ret2 := minDistDp(m)
   106  	t.Log(ret2)
   107  
   108  }