【二分与三分06】Elevator Stopping Plan

题目来源:


题目大意:

一个公司只有一部电梯,电梯运行4s/层,停留10s/层(最顶层不用计算停留时间),人爬楼20s/层。

给出n个人要停留的层数(按从低层到高层顺序),要使最后到达的人花费时间最小,那么怎么安排在哪些楼层停留?


解题思路

二分法。

用一个数组表示停留层数,停的层为1,其他为0(因为设的全局数组所以每次开始前要清空),并记录停留的top层是哪层(输入的最后一层)

二分初始下界简单设为0(或者是4*(top-1)),上界为20*(top-1)(电梯坏了大家都去爬楼吧~),二分mid为暂定需要的最大时间,从不能用爬楼到达的层数开始,找到要求要停留的层数,如果到达这个层数的时间4*所在楼层-1+10*之前停留过的次数大于mid,就gg了,否的话开始跳层,先跳到j层(从j层通过下楼可以在mid时间内到达原i层(st*10 + (j-1)*4 + (j-i)*20 = mid)),然后跳到新i层(从j层可以通过上楼到达新i层(st*10 + (i-1)*4 + (i-j)*20 = mid)),下一个层数从新i+1层开始。

因为st是全局变量所以可能会出现进入了check但i已超过最大层情况,st先变成了0,所以最后还要check一下最终得出的时间把停留楼层再确定一遍。

PS:这个题目输出样例给错了,第一个样例对应“3 4 5 10”输出的是“2 5 10”而不是“2 4 10”请大家注意一下

我搞了一个下午结果最后发现是题目有错,太崩溃了,我还以为只能在需要停的地方停而且尽量上楼,比如4 6 10层的话得在4层停,而不是5层,但得承认我思考有错吧……毕竟这样的话跳层万一跳过了不就gg了吗,总之,太过依赖测试数据而不仔细思考细节的话是很容易出错的,得改。

AC代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 35

int T, top, st;
int fl[N], stop[N];

int check(int mid)
{
    int i, j, temp;
    st = 0;
    for (i=mid/20+2;i<=top;i++)
    {
        while (!fl[i] && i<top)
        {
            i++;
        }
        temp = (i-1)*4 + st*10;
        if (temp>mid)
        {
            return 0;
        }
        j = (mid - 10*st + 20*i + 4)/24;
        i = (mid - 10*st + 16*j + 4)/20;
        stop[st++] = j;
    }
    return 1;
}

int elevator(int l, int r)
{
    int mid;
    while (l<r)
    {
        mid = (l+r)/2;
        if (check(mid))
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    return r;
}

int main()
{
    int i, max, t, temp;
    while (scanf("%d",&T) && T)
    {
        for (i=0;i<N;i++)
        {
            fl[i] = 0;
        }
        for (i=0;i<T;i++)
        {
            scanf("%d",&t);
            fl[t] = 1;
            top = t;
        }
        max = (top-1)*20;
        temp = elevator(0,max);
        printf("%d\n",temp);
        check(temp);
        printf("%d ",st);
        for (i=0;i<st;i++)
        {
            printf("%d%c",stop[i],i==st-1 ? '\n':' ');
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值