在一行上输入
个整数
,含义分别为:
——行星数量,且
为偶数;
——技能可使用的最大次数;
——起点与终点的编号;
——每次普通移动的距离。
输出一个整数,表示最少所需时间;若无法到达,则输出
。
4 0 1 2 2 1
2
你可以先顺时针移动颗行星到达编号
,再逆时针移动
颗行星到达编号
,共耗时
。
4 114514 1 3 1 1
1
4 114514 1 2 2 2
-1
package main
import (
"bufio"
"fmt"
"os"
)
/*
BFS
visited[pos][tp] 表示在位置 pos,使用 tp 次传送的状态是否访问过
tp 只有 0 和 1 两种状态(因为用两次等于没用)
queue := []State
*/
type State struct {
pos int // 当前位置 (0 ~ n-1)
steps int // 已用步数
tp int // 是否使用过传送: 0 或 1
}
func minSteps(n, k, a, b, x, y int) int {
a-- // 转为 0-indexed
b-- // 转为 0-indexed
if a == b {
return 0
}
// visited[pos][tp] 表示在位置 pos,使用 tp 次传送的状态是否访问过
// tp 只有 0 和 1 两种状态(因为用两次等于没用)
visited := make([][]bool, n)
for i := range visited {
visited[i] = make([]bool, 2) // tp: 0 或 1
}
// BFS 队列
queue := []State{{a, 0, 0}}
visited[a][0] = true
for len(queue) > 0 {
cur := queue[0]
queue = queue[1:] // 出队
nextSteps := cur.steps + 1
// 1. 顺时针移动 x 步
p1 := (cur.pos + x) % n
if !visited[p1][cur.tp] {
if p1 == b {
return nextSteps
}
visited[p1][cur.tp] = true
queue = append(queue, State{p1, nextSteps, cur.tp})
}
// 2. 逆时针移动 y 步
p2 := (cur.pos - y + n) % n // +n 防止负数
if !visited[p2][cur.tp] {
if p2 == b {
return nextSteps
}
visited[p2][cur.tp] = true
queue = append(queue, State{p2, nextSteps, cur.tp})
}
// 3. 使用传送技能(跳到对面)
if cur.tp == 0 && k >= 1 { // 还没用过,且 k >= 1
p3 := (cur.pos + n/2) % n
if !visited[p3][1] {
if p3 == b {
return nextSteps
}
visited[p3][1] = true
queue = append(queue, State{p3, nextSteps, 1})
}
}
}
return -1
}
func main() {
reader := bufio.NewReader(os.Stdin)
var n, k, a, b, x, y int
_, err := fmt.Fscan(reader, &n, &k, &a, &b, &x, &y)
if err != nil {
panic(err)
}
result := minSteps(n, k, a, b, x, y)
fmt.Println(result)
}