题目来源:
题目大意:
一个公司只有一部电梯,电梯运行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;
}