package main
import (
"container/heap"
"fmt"
"math"
"math/rand"
"sort"
"time"
)
func Times1(nums int, jobTimes []int, orders [][]int) [][]int {
lines := make([]int, nums)
n := len(orders)
ans := make([][]int, n)
for i := 0; i < n; i++ {
ans[i] = make([]int, 2)
}
for i := 0; i < n; i++ {
start, typ := orders[i][0], orders[i][1]
usei := -1
for j := 0; j < nums; j++ {
if lines[j] <= start {
usei = j
break
}
}
if usei != -1 {
ans[i][0] = usei
ans[i][1] = start + jobTimes[typ]
} else {
early := math.MaxInt32
for j := 0; j < nums; j++ {
if lines[j] < early {
early = lines[j]
usei = j
}
}
ans[i][0] = usei
ans[i][1] = early + jobTimes[typ]
}
lines[usei] = ans[i][1]
}
return ans
}
type Line struct {
time int
index int
}
type WakeUpHeap []*Line
func (h WakeUpHeap) Len() int { return len(h) }
func (h WakeUpHeap) Less(i, j int) bool {
if h[i].time != h[j].time {
return h[i].time < h[j].time
}
return h[i].index < h[j].index
}
func (h WakeUpHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *WakeUpHeap) Push(x interface{}) {
*h = append(*h, x.(*Line))
}
func (h *WakeUpHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[:n-1]
return x
}
type IndexHeap []*Line
func (h IndexHeap) Len() int { return len(h) }
func (h IndexHeap) Less(i, j int) bool { return h[i].index < h[j].index }
func (h IndexHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *IndexHeap) Push(x interface{}) {
*h = append(*h, x.(*Line))
}
func (h *IndexHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[:n-1]
return x
}
func Times2(nums int, componets []int, orders [][]int) [][]int {
n := len(orders)
// 睡眠堆
sleepLines := make(WakeUpHeap, 0)
heap.Init(&sleepLines)
// 可用堆
canUseLines := make(IndexHeap, nums)
for i := 0; i < nums; i++ {
canUseLines[i] = &Line{0, i}
}
heap.Init(&canUseLines)
ans := make([][]int, n)
for i := 0; i < n; i++ {
ans[i] = make([]int, 2)
}
for i := 0; i < n; i++ {
startTime, jobType := orders[i][0], orders[i][1]
// 当前订单在start时刻下单,所有唤醒时间比time早的流水线全可以考虑
for len(sleepLines) > 0 && sleepLines[0].time <= startTime {
heap.Push(&canUseLines, heap.Pop(&sleepLines))
}
// 如果可以使用的流水线不存在
// 比如,2条流水线
// 第0个订单,1时刻开始,用时100万,流水线A在100万+1时刻醒来
// 第1个订单,2时刻开始,用时100万,流水线B在100万+2时刻醒来
// 轮到第3个订单,3时刻开始,用时100万
// 会发现可用流水线已经没有了,此时需要等到流水线A在100万+1时刻醒来,做当前订单
var use *Line
if len(canUseLines) == 0 {
// 如果当前时刻,可以使用的流水线不存在,需要等到可以唤醒的最早那个
// 如果可以唤醒的最早流水线,不只一个
// 选编号小的,看比较器的注释
use = heap.Pop(&sleepLines).(*Line)
ans[i][1] = use.time + componets[jobType]
} else {
// 如果当前时刻,可以使用的流水线存在,需要使用编号最小的
use = heap.Pop(&canUseLines).(*Line)
ans[i][1] = startTime + componets[jobType]
}
ans[i][0] = use.index
use.time = ans[i][1]
heap.Push(&sleepLines, use)
}
return ans
}
func randomArray(n, v int) []int {
ans := make([]int, n)
rand.Seed(time.Now().UnixNano())
for i := 0; i < n; i++ {
ans[i] = rand.Intn(v) + 1
}
return ans
}
func randomMatrix(n, a, b int) [][]int {
ans := make([][]int, n)
rand.Seed(time.Now().UnixNano())
for i := 0; i < n; i++ {
ans[i] = []int{rand.Intn(a) + 1, rand.Intn(b)}
}
return ans
}
func main() {
N := 100
M := 300
V := 10000
testTimes := 5000
fmt.Println("功能测试开始")
for i := 0; i < testTimes; i++ {
nums := rand.Intn(N) + 1
orderNumber := rand.Intn(M) + 1
types := rand.Intn(N) + 1
componets := randomArray(types, V)
orders := randomMatrix(orderNumber, V, types)
sort.Slice(orders, func(i, j int) bool { return orders[i][0] < orders[j][0] })
ans1 := Times1(nums, componets, orders)
ans2 := Times2(nums, componets, orders)
for j := range ans1 {
if ans1[j][0] != ans2[j][0] || ans1[j][1] != ans2[j][1] {
fmt.Println("出错了!")
fmt.Println(nums)
for _, num := range componets {
fmt.Printf("%d ", num)
}
fmt.Println()
for _, order := range orders {
fmt.Printf("(%d, %d) ", order[0], order[1])
}
fmt.Println()
fmt.Print("ans1 : ")
for _, cur := range ans1 {
fmt.Printf("(%d, %d) ", cur[0], cur[1])
}
fmt.Println()
fmt.Print("ans2 : ")
for _, cur := range ans2 {
fmt.Printf("(%d, %d) ", cur[0], cur[1])
}
fmt.Println()
return
}
}
}
fmt.Println("功能测试结束")
fmt.Println("性能测试开始")
N = 100000
M = 500000
V = 100000
nums := N
componets := randomArray(N, V)
orders := randomMatrix(M, V, N)
sort.Slice(orders, func(i, j int) bool { return orders[i][0] < orders[j][0] })
fmt.Println("流水线数量 : ", N)
fmt.Println("订单数量 : ", M)
fmt.Println("时间数值范围 : ", V)
start := time.Now()
Times2(nums, componets, orders)
end := time.Now()
fmt.Println("运行时间 : ", end.Sub(start).Milliseconds(), " 毫秒")
fmt.Println("性能测试结束")
}
评论