Algorithm 电梯最小距离算法

Algorithm 电梯最小距离算法,algorithm,Algorithm,我有一栋只有一部电梯的大楼,我需要为这部电梯找到一个算法。我们得到了这种形式的对象列表:{i->j},其中i是住户想要乘坐电梯的楼层,j是住户想要下车的楼层 有无限多的人可以同时使用电梯,人们在电梯里呆多久无关紧要。电梯从一楼开始 我在网上查了一下,发现了“电梯算法”,但它并没有真正帮助我。上面说我应该一路上去,然后一路下来。但是当一个居民想从1岁到100岁的时候,另一个居民希望从50岁到49岁。使用上述算法,需要151层楼的距离。如果我改为沿着这条路径:1->50->49->100,它只需要1

我有一栋只有一部电梯的大楼,我需要为这部电梯找到一个算法。我们得到了这种形式的对象列表:
{i->j}
,其中
i
是住户想要乘坐电梯的楼层,
j
是住户想要下车的楼层

有无限多的人可以同时使用电梯,人们在电梯里呆多久无关紧要。电梯从一楼开始

我在网上查了一下,发现了“电梯算法”,但它并没有真正帮助我。上面说我应该一路上去,然后一路下来。但是当一个居民想从1岁到100岁的时候,另一个居民希望从50岁到49岁。使用上述算法,需要151层楼的距离。如果我改为沿着这条路径:1->50->49->100,它只需要102层,这更好


我应该使用什么算法?

您的问题反映了磁盘头调度算法

查看vs

在某些情况下,sstf获胜,但如果是50比10,你也有2比100、3比100、4比100、5比100、6比100等。你可以看到你将开销添加到所有其他人身上。此外,如果传入请求具有较小的寻道时间,则可能会发生(类似于进程调度)


在您的情况下,这实际上取决于请求是静态的还是动态的。如果您想最小化差异,请使用scan/cscan等。

这里有一种方法可以将此问题表述为基于时间的整数程序。(生成所有约束似乎有些过分,但可以保证生成最佳解决方案)

假设电梯从楼层
F
F+1
或到
F-1
需要1个单位的时间

洞察:我们利用这样一个事实:在任何时候,
t
,只有一个决策需要做出。是上升还是下降。这就是我们问题的决策变量。如果电梯在时间t向上移动,则DIR_t=+1,否则为-1

我们想尽量缩短所有乘客到达目的地的时间

这张桌子更清楚了

Time    FLOOR_t   Dir_t
1        1          1
2       2           1
3       3           1
4       4           1
...    ...          ...
49      49          1
50      50          -1
51      49          1
52      50          1
...     
100     99          1
101     100         NA
现在,让我们把乘客带进来。有P个乘客,每个人都想从
SF
EF
(起点楼层到终点楼层,终点楼层。)

因此,我们为每位乘客提供
(SF\u p,EF\u p)

约束条件 我们知道时间t时电梯所在的楼层是

 F_t = F_t-1 + DIR_t-1
(F0=0,DIR_0=1,F1=1只是为了开始工作。)

现在,让
ST_p
成为乘客p开始电梯旅程的时刻。让
ET_p
为乘客p结束电梯旅程的时间瞬间。 请注意,
SF
EF
是提供给我们的输入参数,但
ST
ET
是IP在求解时将设置的变量。也就是说,地板是给我们的,我们必须跟上时代

   ST_p = t if F_t = SF_p  # whenever the elevator comes to a passenger's starting floor, their journey starts.       
   ET_p = t if F_t = EF_p AND ST_p > 0 (a passenger cannot end their journey before it commenced.)
   This can be enforced by introducing new 0/1 indicator variables.

   ETp > STp # you can only get off after you got on
   
最后,让我们介绍一个数字
T
,它是完成整套行程的时间。它是每个p的所有ET的最大值。这是需要尽量减少的

   T > ET_p for all p # we want to find the time when the last passenger gets off.
配方 总而言之:

   Min T
   
   T > ET_p for all p
   F_t = F_t-1 + DIR_t-1
   ETp > STp # you can only get off after you got on 
   ST_p = t if F_t = SF_p  # whenever the elevator some to a passenger's starting floor, their journey starts.
   ET_p = t if F_t = EF_p AND ST_p > 0
   ET_p >= 1 #everyone should end their journey. Otherwise model will give 0 as the obj function value.
   DIR_t = (+1, -1) # can be enforced with 2 binary variables if needed.

现在,在解决了这个IP问题之后,可以使用每个
t
的每个
DIR\u t
的值来追踪确切的行程。对于每个
t

,有一个多项式时间动态程序,其运行时间不依赖于楼层数。如果我们贪婪地接送乘客并让他们等待,那么相关的状态是电梯访问的楼层间隔(因此乘客接送),电梯最近上下的楼层,和两个可选值:为了让乘客下车,它必须访问的最低楼层和最高楼层。所有这些状态都可以用五个乘客的身份加上恒定数量的位来描述


我很确定这里有改进的余地。

在对C.B.答案的评论中,OP评论:“请求是静态的。一开始我得到了完整的列表。”我欢迎反例和/或其他反馈,因为在我看来,如果我们提前得到所有行程,如果我们考虑以下问题,可以大大减少:

  • 由于电梯的容量是无限的,因此任何一次上电梯的行程都低于我们将要参观的最高楼层,这与我们的计算无关。由于我们保证在到达最高点的途中通过所有的上下车,我们可以在考虑下降行程后将它们放在我们的日程安排中

  • 同一方向的其他行程中“包含”的任何行程也不相关,因为我们将在“最外层”行程中通过这些上下车,并且在考虑这些行程后,可能会适当安排这些行程

  • 任何重叠的下行行程可能会因一个很快就会显现的原因而合并

  • 任何下降行程发生在到达最高点之前或之后(皮卡车到达的最高楼层除外)。我们确定在最高点之前发生的所有下降行程(仅考虑“外容器”类型和两个或多个重叠行程作为一次行程)的最佳计划是在我们上升时一个接一个地进行,因为我们无论如何都在上升的过程中

  • 我们如何确定哪些下降行程应在最高点之后发生

    我们参考一个点进行计算,
    TOP
    。让我们调用包含到达的最高楼层
    H
    和到达的最高楼层
    HFR
    的行程。如果HFR
    HFR
    是一个拾音器,
    H
    正在下降,并且
    TOP=H\U衰减
    。如果
    HFR
    是一个下降值,
    H
    是上升的,
    TOP=HFR

    这是一个下降的行程
    import Data.List (sort,sortBy)
    
    trips = [(101,100),(50,49),(25,19),(99,97),(95,93),(30,20),(35,70),(28,25)]
    
    isDescending (a,a') = a > a'
    
    areDescending a b = isDescending a && isDescending b
    
    isContained aa@(a,a') bb@(b,b') = areDescending aa bb && a < b && a' > b'
    
    extends aa@(a,a') bb@(b,b') = areDescending aa bb && a <= b && a > b' && a' < b'
    
    max' aa@(a,a') bb@(b,b') = if (maximum [b,a,a'] == b) || (maximum [b',a,a'] == b')
                                  then bb
                                  else aa
    
    (outerDescents,innerDescents,ascents,topTrip) = foldr f ([],[],[],(0,0)) trips where
      f trip (outerDescents,innerDescents,ascents,topTrip) = g outerDescents trip ([],innerDescents,ascents,topTrip) where
        g [] trip (outerDescents,innerDescents,ascents,topTrip) = (trip:outerDescents,innerDescents,ascents,max' trip topTrip)
        g (descent:descents) trip (outerDescents,innerDescents,ascents,topTrip)
          | not (isDescending trip) = (outerDescents ++ (descent:descents),innerDescents,trip:ascents,max' trip topTrip)
          | isContained trip descent = (outerDescents ++ (descent:descents),trip:innerDescents,ascents,topTrip)
          | isContained descent trip = (trip:outerDescents ++ descents,descent:innerDescents,ascents,max' trip topTrip)
          | extends trip descent = ((d,t'):outerDescents ++ descents,(t,d'):innerDescents,ascents,max' topTrip (d,t'))
          | extends descent trip = ((t,d'):outerDescents ++ descents,(d,t'):innerDescents,ascents,max' topTrip (t,d'))
          | otherwise = g descents trip (descent:outerDescents,innerDescents,ascents,topTrip)
         where (t,t') = trip
               (d,d') = descent
    
    top = snd topTrip
    
    scheduleFirst descents = (sum $ map (\(from,to) -> 2 * (from - to)) descents)
                           > top - (snd . last) descents
    
    (descentsScheduledFirst,descentsScheduledAfterTop) =
      (descentsScheduledFirst,descentsScheduledAfterTop) where
        descentsScheduledAfterTop = (\x -> if not (null x) then head x else [])
                               . take 1 . filter scheduleFirst
                               $ foldl (\accum num -> take num sorted : accum) [] [1..length sorted]
        sorted = sortBy(\a b -> compare b a) outerDescents
        descentsScheduledFirst = if null descentsScheduledAfterTop
                                     then sorted
                                     else drop (length descentsScheduledAfterTop) sorted
    
    scheduled = ((>>= \(a,b) -> [a,b]) $ sort descentsScheduledFirst) 
             ++ (if isDescending topTrip then [] else [top])
             ++ ((>>= \(a,b) -> [a,b]) $ sortBy (\a b -> compare b a) descentsScheduledAfterTop)
    
    place _      []             _    _     = error "topTrip was not calculated."
    place floor' (floor:floors) prev (accum,numStops)
      | floor' == prev || floor' == floor = (accum ++ [prev] ++ (floor:floors),numStops)
      | prev == floor                     = place floor' floors floor (accum,numStops)
      | prev < floor                      = f
      | prev > floor                      = g
     where f | floor' > prev && floor' < floor = (accum ++ [prev] ++ (floor':floor:floors),numStops)
             | otherwise                       = place floor' floors floor (accum ++ [prev],numStops + 1)
           g | floor' < prev && floor' > floor = (accum ++ [prev] ++ (floor':floor:floors),numStops)
             | otherwise                       = place floor' floors floor (accum ++ [prev],numStops + 1)
    
    schedule trip@(from,to) floors = take num floors' ++ fst placeTo
      where placeFrom@(floors',num) = place from floors 1 ([],1)
            trimmed = drop num floors'
            placeTo = place to (tail trimmed) (head trimmed) ([],1)
    
    solution = foldl (\trips trip -> schedule trip trips) scheduled (innerDescents ++ ascents) 
    
    main = do print trips
              print solution
    
    *Main> main
    [(101,100),(50,49),(25,19),(99,97),(95,93),(30,20),(35,70),(28,25)]
    [1,25,28,30,25,20,19,35,50,49,70,101,100,99,97,95,93]