常规解法
常规思路需要 O(n*n) 的时间复杂度 才能计算出来
具体做法就是 穷举,从 0-n 不停的作为出发点测试
基于常规进行优化
模拟常规代码
for i~ n {
can[i] = 0
for j=i;j<i+n;j++ {
j = j %n
sum += oil[j] - dis[j]
if sum < 0 {
break
}
}
if j == i+n {
can[i] = 1
}
}我们发现 其实我们在反复探测从不同出发点是否能够走通,走通就标记一下,其实我们中间有好多次重复的计算,比如 以下标0 为起点,需要计算 0-n ,从下标1触发需要计算 1-n -0 中间绝大部分都是重复的,如何解?
因为每一次的起点是不同的,所以我们需要对起点之后每一站从新计算,才能算准油量是否足够。反过来想,如果我们将一个点作为出发点,当油量不够的时候,直接“回朔” 加上起点之前的节点的油量是否就可以规避反复的计算,但是此时,这个循环的意义会缩减为 “寻找一个点A,从这个点出发一定能到完全程?”
我们得到了点A,同样的思维,我们从点A出发,如果一个点剩余静里程大于0 ,则上个点一定也能走完全程,接着想上一个点探测,如果小于0呢!则这个节点就要暂时放弃,累加/回朔上节点的上一个节点,继续探测。
完整代码
package main
import (
"fmt"
"os"
"bufio"
"strconv"
)
func main(){
var n int
fmt.Scanf("%d",&n)
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
oil := make([]int,n)
dis := make([]int,n)
for i:=0;i<n;i++{
if scanner.Scan(){
oil[i],_ = strconv.Atoi(scanner.Text())
}
}
for i:=0;i<n;i++{
if scanner.Scan(){
dis[i],_ = strconv.Atoi(scanner.Text())
}
}
helper(oil,dis,n)
return
}
func helper(oil,dis []int,n int){
//计算某个位置的静里程数
for i:=0;i<n;i++{
oil[i] -= dis[i]
dis[i] = -1
}
start := 0
end := 1
ans := 0
//第一遍查找,确定是否可以走通
for start != end {
if ans>=0{
ans += oil[end]
end = (end +1) % n
}else{
ans += oil[start]
start = (start-1+n) %n
}
}
//排除不合规的条件
if ans < 0 {
for i:=0;i<n;i++{
fmt.Printf("%d ",0)
}
return
}
//至此,从一个可以走通的地方不停的倒序探索,直到探索完
cur := start;
ans = oil[start]
for dis[cur] == -1 {
//可达,探索上一个位置
if ans >=0 {
dis[cur] = 1
cur = (cur -1 +n) %n
ans = oil[cur]
}else{ //不可达 累加上一个位置并探索
dis[cur] = 0
cur = (cur-1+n) %n
ans += oil[cur]
}
}
//输出结果
for i:=0;i<n;i++{
fmt.Printf("%d ",dis[i])
}
return
}



京公网安备 11010502036488号