1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
   | package main
  import ( 	"container/heap" 	"fmt" 	"math" )
  func main() { 	graph := [][]int{ 		{1, 1, 0}, 		{1, 0, 1}, 		{0, 0, 0}, 		{0, 0, 1}, 	} 	n, m := len(graph), len(graph[0])
  	fmt.Println(dijkstra(graph)[n-1][m-1]) }
  type State struct { 	x                 int 	y                 int 	distanceFromStart int }
  func dijkstra(graph [][]int) [][]int { 	n, m := len(graph), len(graph[0]) 	minDistanceTo := make([][]int, n)
  	for i := range minDistanceTo { 		minDistanceTo[i] = make([]int, m) 		for j := range minDistanceTo[i] { 			minDistanceTo[i][j] = math.MaxInt 		} 	} 	minDistanceTo[0][0] = 0
  	pq := PriorityQueue{} 	heap.Push(&pq, &State{0, 0, 0})
  	 	directions := [][]int{ 		{1, 0}, 		{0, 1}, 		{0, -1}, 	}
  	for pq.Len() > 0 { 		currState := heap.Pop(&pq).(*State) 		currX, currY, currDist := currState.x, currState.y, currState.distanceFromStart
  		if minDistanceTo[currX][currY] < currDist { 			continue 		}
  		for _, d := range directions { 			nextX, nextY := currX+d[0], currY+d[1] 			 			 			if nextX >= n || nextY < 0 || nextY >= m { 				continue 			}
  			weight := 1 			if graph[nextX][nextY] != graph[currX][currY] { 				weight += 1 			}
  			distanceToNext := minDistanceTo[currX][currY] + weight
  			if distanceToNext < minDistanceTo[nextX][nextY] { 				minDistanceTo[nextX][nextY] = distanceToNext 				heap.Push(&pq, &State{nextX, nextY, distanceToNext}) 			} 		} 	}
  	return minDistanceTo }
  type PriorityQueue []*State
  func (pq PriorityQueue) Len() int { 	return len(pq) }
  func (pq PriorityQueue) Less(i, j int) bool { 	return pq[i].distanceFromStart < pq[j].distanceFromStart }
  func (pq PriorityQueue) Swap(i, j int) { 	pq[i], pq[j] = pq[j], pq[i] }
  func (pq *PriorityQueue) Push(x interface{}) { 	*pq = append(*pq, x.(*State)) }
  func (pq *PriorityQueue) Pop() interface{} { 	old := *pq 	n := len(old) 	item := old[n-1] 	old[n-1] = nil 	*pq = old[:n-1] 	return item }
 
  |