楼教主男人八题(告一段落)

ACM比赛整理

共 2350字,需浏览 5分钟

 ·

2022-01-04 15:12

各位老板好,我是自在飞花。

细心的老铁可能发现了我没有讲第七题。

这个是因为第七题太难了。倒不是代码实现有多么难,而是把思路讲明白很难。

这个题的正解是 「Garsia-Wachs 算法」,一种在已知键值和查询概率的前提下,构造最优二叉搜索树的算法。

我大约想了三周了,也没想出比较易懂的讲解方式,又不想抄书,所以暂且放弃了,等哪天顿悟了再回来补上。

另外,我为大家找到了一个证明,很严谨也很晦涩,有兴趣的老铁可以看下 《The Art of Computer Programming》第3卷 6.2.2 节 Algorithm G 和 Lemma W,Lemma X,Lemma Y,Lemma Z。PDF下载方式见左下角阅读原文。

好了,接下来进入第八题,POJ 1744 《Elevator Stopping Plan》。

题目链接

http://poj.org/problem?id=1744

题目描述

There are H floors in GaoKe Hall.

It takes 4 seconds for the elevator to raise one floor. It means: It costs seconds if the elevator goes from the 1 st floor to the nth floor without stop. And the elevator stops 10 second once.

So, if the elevator stops at each floor, it will cost seconds (It is not necessary to calculate the stopping time at nth floor).

In another way, it takes 20 seconds for the workers to go up or down one floor. It takes seconds for them to walk from the 1 st floor to the nth floor.

After thinking over for a long time, Hal finally found a way to improve this situation. He told the elevator man his idea:

First, the elevator man asks the people which floors they want to go. He will then design a stopping plan which minimize the time the last person need to arrive the floor where his office locates.

For example, if the elevator is required to stop at the 4th , 5th and 10th floor, the stopping plan would be: the elevator stops at 4th and 10th floor. Because the elevator will arrive 4 th floor at second, then it will stop 10 seconds, then it will arrive 10 th floor at second. People who want to go 4 th floor will reach their office at 12.

Second, people who want to go to 5 th floor will reach at second and people who want to go to 10 th floor will reach at 46 second. Therefore it takes 46 seconds for the last person to reach his office. It is a good deal for all people.

Now, you are supposed to write a program to help the elevator man to design the stopping plan,which minimize the time the last person needs to arrive at his floor.

题目输入

The input consists of several test cases. Each test case is in a single line as the following:

It means, there are totally n floors at which the elevator need to stop, and n = 0 means no testcases any more.

f1 f2 ... fn are the floors at which the elevator is to be stopped (1<=n<=30000, 2<= f1< f2 ... fn<=30000).

Every number is separated by a single space.

题目输出

For each testcase, output the time the last reading person needs in the a single line

输入样例

3 4 5 10
1 2
0

输出样例

46
4

一般看到最大的最小值最早的最晚时间点等类似字眼,都可考虑用二分来解决。

对于给定的输入,必定存在一个最优解,假设该最优解消耗 秒。那么对于任意的时间限制 ,都存在解决方案。对于任意,都不可能存在解决方案(不然 就不是最优解了)。

不难发现,这符合二分的前提——的单调性。那么问题变成了,在给定的输入上,判断在 秒内能否将所有人送至指定楼层。如果存在,则说明 ,反之说明。接下来,我们将这个存在性问题转化为区间覆盖问题来解决。

不妨先假设,在最优方案中,电梯有 个停靠点,第 停靠点的楼层为 ,停靠该楼层的时间点为 。因为初始时电梯在第一层,不妨设

我们让每个停靠点都覆盖区间 内的所有楼层。覆盖的含义是:员工在 时刻,在 走下电梯,可以在 秒内步行至 中的任意一层。不难得出:

因为所有员工都必须在 时间内到达各自的楼层,所以这 个停靠点要覆盖输入的

那么问题变成了构造。接着使用贪心的思路来构造:

  • 让每个区间尽可能的长——这是的尽可能小,即停靠带来的时间花费更小。
  • 任意两个区间没有交集——有交集意味着浪费。

首先,易得 。接着可在已知 的前提下,求解

因为要覆盖所有的 ,那么第一个大于 就是 ,则有:

基于 以及 列出不等式如下:

移项得:

取最大值:

=

易得:

如上所述,只要能构造出停靠点,就说明,否则

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

int f[30000];

bool check(int mid, int n) {
  int f0 = 1, t0 = 0, l0 = 1, r0 = mid/20 + 1;
  int i = 0;
  int stop_cost = 0;
  while (i < n) {
    // 寻找 fx
    while (f[i] <= r0) {
      i++;
    }
    if (i < n) {
      int l1 = f[i];
      int f1 = (mid+4*f0+20*l1-stop_cost-t0)/24;
      int t1 = t0 + stop_cost + (f1-f0)*4;
      int r1 = f1 + (mid-t1)/20;
      // 剩下的时间不足了
      if (f1 == f0) {
        return false;
      }
      stop_cost = 10;
      l0 = l1, r0 = r1, t0 = t1, f0 = f1;
    }
  }
  return true;
}

int main() {
  int n;
  while(scanf("%d", &n) && n) {
    for (int i = 0; i < n; i++) {
      scanf("%d", &f[i]);
    }
    int L = (f[n-1]-1)*4, R = (f[n-1]-1)*10;

    while(L <= R) {
      int mid = (L+R)>>1;
      if (check(mid, n)) {
        R = mid-1;
      } else {
        L = mid+1;
      }
    }
    printf("%d\n", R+1);
  }
  return 0;
}


浏览 59
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报