forked from doocs/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSolution.go
111 lines (106 loc) · 2.64 KB
/
Solution.go
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
108
109
110
111
func canMouseWin(grid []string, catJump int, mouseJump int) bool {
m, n := len(grid), len(grid[0])
catStart, mouseStart, food := 0, 0, 0
dirs := []int{-1, 0, 1, 0, -1}
gMouse := make([][]int, m*n)
gCat := make([][]int, m*n)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
c := grid[i][j]
if c == '#' {
continue
}
v := i*n + j
if c == 'C' {
catStart = v
} else if c == 'M' {
mouseStart = v
} else if c == 'F' {
food = v
}
for d := 0; d < 4; d++ {
a, b := dirs[d], dirs[d+1]
for k := 0; k <= mouseJump; k++ {
x, y := i+k*a, j+k*b
if !(0 <= x && x < m && 0 <= y && y < n && grid[x][y] != '#') {
break
}
gMouse[v] = append(gMouse[v], x*n+y)
}
for k := 0; k <= catJump; k++ {
x, y := i+k*a, j+k*b
if !(0 <= x && x < m && 0 <= y && y < n && grid[x][y] != '#') {
break
}
gCat[v] = append(gCat[v], x*n+y)
}
}
}
}
return calc(gMouse, gCat, mouseStart, catStart, food) == 1
}
func calc(gMouse, gCat [][]int, mouseStart, catStart, hole int) int {
n := len(gMouse)
degree := make([][][]int, n)
ans := make([][][]int, n)
for i := 0; i < n; i++ {
degree[i] = make([][]int, n)
ans[i] = make([][]int, n)
for j := 0; j < n; j++ {
degree[i][j] = make([]int, 2)
ans[i][j] = make([]int, 2)
degree[i][j][0] = len(gMouse[i])
degree[i][j][1] = len(gCat[j])
}
}
q := list.New()
for i := 0; i < n; i++ {
ans[hole][i][1] = 1
ans[i][hole][0] = 2
ans[i][i][1] = 2
ans[i][i][0] = 2
q.PushBack([]int{hole, i, 1})
q.PushBack([]int{i, hole, 0})
q.PushBack([]int{i, i, 0})
q.PushBack([]int{i, i, 1})
}
for q.Len() > 0 {
front := q.Front()
q.Remove(front)
state := front.Value.([]int)
m, c, t := state[0], state[1], state[2]
currentAns := ans[m][c][t]
for _, prevState := range getPrevStates(gMouse, gCat, m, c, t, ans) {
pm, pc, pt := prevState[0], prevState[1], prevState[2]
if pt == currentAns-1 {
ans[pm][pc][pt] = currentAns
q.PushBack([]int{pm, pc, pt})
} else {
degree[pm][pc][pt]--
if degree[pm][pc][pt] == 0 {
ans[pm][pc][pt] = currentAns
q.PushBack([]int{pm, pc, pt})
}
}
}
}
return ans[mouseStart][catStart][0]
}
func getPrevStates(gMouse, gCat [][]int, m, c, t int, ans [][][]int) [][]int {
pt := t ^ 1
pre := [][]int{}
if pt == 1 {
for _, pc := range gCat[c] {
if ans[m][pc][1] == 0 {
pre = append(pre, []int{m, pc, pt})
}
}
} else {
for _, pm := range gMouse[m] {
if ans[pm][c][0] == 0 {
pre = append(pre, []int{pm, c, pt})
}
}
}
return pre
}