Featured image of post 2532. 过桥的时间

2532. 过桥的时间

题目描述

共有 k 位工人计划将 n 个箱子从旧仓库移动到新仓库。给你两个整数 nk,以及一个二维整数数组 time ,数组的大小为 k x 4 ,其中 time[i] = [leftToRighti, pickOldi, rightToLefti, putNewi] 。

一条河将两座仓库分隔,只能通过一座桥通行。旧仓库位于河的右岸,新仓库在河的左岸。开始时,所有 k 位工人都在桥的左侧等待。为了移动这些箱子,第 i 位工人(下标从 0 开始)可以:

  • 从左岸(新仓库)跨过桥到右岸(旧仓库),用时 leftToRighti 分钟。
  • 从旧仓库选择一个箱子,并返回到桥边,用时 pickOldi 分钟。不同工人可以同时搬起所选的箱子。
  • 从右岸(旧仓库)跨过桥到左岸(新仓库),用时 rightToLefti 分钟。
  • 将箱子放入新仓库,并返回到桥边,用时 putNewi 分钟。不同工人可以同时放下所选的箱子。

如果满足下面任一条件,则认为工人 i效率低于 工人 j

  • leftToRighti + rightToLefti > leftToRightj + rightToLeftj
  • leftToRighti + rightToLefti == leftToRightj + rightToLeftj 且 i > j

工人通过桥时需要遵循以下规则:

  • 如果工人 x 到达桥边时,工人 y 正在过桥,那么工人 x 需要在桥边等待。
  • 如果没有正在过桥的工人,那么在桥右边等待的工人可以先过桥。如果同时有多个工人在右边等待,那么 效率最低 的工人会先过桥。
  • 如果没有正在过桥的工人,且桥右边也没有在等待的工人,同时旧仓库还剩下至少一个箱子需要搬运,此时在桥左边的工人可以过桥。如果同时有多个工人在左边等待,那么 效率最低 的工人会先过桥。

所有 n 个盒子都需要放入新仓库,请你返回最后一个搬运箱子的工人 到达河左岸 的时间。

示例 1:

  • 输入:n = 1, k = 3, time = [[1,1,2,1],[1,1,3,1],[1,1,4,1]]
  • 输出:6
  • 解释:
    • 从 0 到 1 :工人 2 从左岸过桥到达右岸。
    • 从 1 到 2 :工人 2 从旧仓库搬起一个箱子。
    • 从 2 到 6 :工人 2 从右岸过桥到达左岸。
    • 从 6 到 7 :工人 2 将箱子放入新仓库。
    • 整个过程在 7 分钟后结束。因为问题关注的是最后一个工人到达左岸的时间,所以返回 6 。

示例 2:

  • 输入:n = 3, k = 2, time = [[1,9,1,8],[10,10,10,10]]
  • 输出:50
  • 解释:
    • 从 0 到 10 :工人 1 从左岸过桥到达右岸。
    • 从 10 到 20 :工人 1 从旧仓库搬起一个箱子。
    • 从 10 到 11 :工人 0 从左岸过桥到达右岸。
    • 从 11 到 20 :工人 0 从旧仓库搬起一个箱子。
    • 从 20 到 30 :工人 1 从右岸过桥到达左岸。
    • 从 30 到 40 :工人 1 将箱子放入新仓库。
    • 从 30 到 31 :工人 0 从右岸过桥到达左岸。
    • 从 31 到 39 :工人 0 将箱子放入新仓库。
    • 从 39 到 40 :工人 0 从左岸过桥到达右岸。
    • 从 40 到 49 :工人 0 从旧仓库搬起一个箱子。
    • 从 49 到 50 :工人 0 从右岸过桥到达左岸。
    • 从 50 到 58 :工人 0 将箱子放入新仓库。
    • 整个过程在 58 分钟后结束。因为问题关注的是最后一个工人到达左岸的时间,所以返回 50 。

提示:

  • 1 <= n, k <= 104
  • time.length == k
  • time[i].length == 4
  • 1 <= leftToRighti, pickOldi, rightToLefti, putNewi <= 1000

解法一:优先队列

 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
var gTime [][]int

type WaitPQ struct {
    sort.IntSlice
}

func (pq *WaitPQ) Push(x interface{}) {
    pq.IntSlice = append(pq.IntSlice, x.(int))
}

func (pq *WaitPQ) Pop() interface{} {
    a := pq.IntSlice
    ret := a[len(a)-1]
    pq.IntSlice = a[:len(a)-1]
    return ret
}

func (pq *WaitPQ) Less(i, j int) bool {
    i, j = pq.IntSlice[i], pq.IntSlice[j]
    x, y := gTime[i][0]+gTime[i][2], gTime[j][0]+gTime[j][2]
    return x > y || x == y && i > j
}

/*---------------------------------------------*/

type WorkPQ struct {
    Arr [][2]int
}

func (pq *WorkPQ) Len() int {
    return len(pq.Arr)
}

func (pq *WorkPQ) Swap(i, j int) {
    pq.Arr[i], pq.Arr[j] = pq.Arr[j], pq.Arr[i]
}

func (pq *WorkPQ) Less(i, j int) bool {
    return pq.Arr[i][0] < pq.Arr[j][0]
}

func (pq *WorkPQ) Push(x interface{}) {
    pq.Arr = append(pq.Arr, x.([2]int))
}

func (pq *WorkPQ) Pop() interface{} {
    a := pq.Arr
    ret := a[len(a)-1]
    pq.Arr = a[:len(a)-1]
    return ret
}

func findCrossingTime(n int, k int, time [][]int) int {
    gTime = time
    waitLeft, waitRight := &WaitPQ{}, &WaitPQ{}
    workLeft, workRight := &WorkPQ{}, &WorkPQ{}
    for i := 0; i < k; i++ {
        heap.Push(waitLeft, i)
    }
    remain, curTime := n, 0
    for remain > 0 || waitRight.Len() > 0 || workRight.Len() > 0 {
        for workRight.Len() > 0 && workRight.Arr[0][0] <= curTime {
            heap.Push(waitRight, workRight.Arr[0][1])
            heap.Pop(workRight)
        }
        for workLeft.Len() > 0 && workLeft.Arr[0][0] <= curTime {
            heap.Push(waitLeft, workLeft.Arr[0][1])
            heap.Pop(workLeft)
        }

        if waitRight.Len() > 0 {
            id := heap.Pop(waitRight).(int)
            curTime += time[id][2]
            heap.Push(workLeft, [2]int{curTime + time[id][3], id})
        } else if remain > 0 && waitLeft.Len() > 0 {
            id := heap.Pop(waitLeft).(int)
            curTime += time[id][0]
            heap.Push(workRight, [2]int{curTime + time[id][1], id})
            remain--
        } else {
            nextTime := math.MaxInt32
            if workLeft.Len() > 0 && workLeft.Arr[0][0] < nextTime {
                nextTime = workLeft.Arr[0][0]
            }
            if workRight.Len() > 0 && workRight.Arr[0][0] < nextTime {
                nextTime = workRight.Arr[0][0]
            }
            if nextTime != math.MaxInt32 && nextTime > curTime {
                curTime = nextTime
            }
        }
    }
    return curTime
}
Licensed under CC BY-NC-SA 4.0
最后更新于 2023/07/07 22:36:34
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计