题目
746:Elevator Stopping Plan
总时间限制: 1000ms 内存限制: 65536kB
描述
ZSoft Corp. is a software company in GaoKe Hall. And the workers in the hall are very hard-working. But the elevator in that hall always drives them crazy. Why? Because there is only one elevator in GaoKe Hall, while there are hundreds of companies in it. Every morning, people must waste a lot of time waiting for the elevator.Hal, a smart guy in ZSoft, wants to change this situation. He wants to find a way to make the elevator work more effectively. But its not an easy job.
There are H floors in GaoKe Hall. It takes 4 seconds for the elevator to raise one floor. It means:It costs (n-1)*4seconds 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 (n-1)4+(n-2)10seconds (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 (n-1)20seconds for them to walk from the 1 st floor to the nth floor. Obviously, it is not a good idea. So some people choose to use the elevator to get a floor which is the nearest to their office.
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 4 th , 5 th and 10 th floor, the stopping plan would be: the elevator stops at 4 th and 10 th floor. Because the elevator will arrive 4 th floor at 34=12second, then it will stop 10 seconds, then it will arrive 10 th floor at 34+10+64=46second. 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 12+20=32second 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:
n f1 f2 … fn
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
来源
LouTiancheng@POJ(楼天城,楼教主,姚期智院士的得意门生)
翻译
746:电梯停车计划
总时间限制: 1000ms内存限制:65536kB
描述
ZSoft Corp.是高科厅的一家软件公司。大厅里的工人非常勤奋。但那个大厅的电梯总是让他们发疯。为什么?因为高科厅只有一部电梯,而里面有数百家公司。每天早上,人们都要浪费很多时间等电梯。哈尔是ZSoft的一个聪明人,他想改变这种情况。他想找到一种方法让电梯更有效地工作。但这不是一件容易的事。
高科楼有H层。电梯上升一层需要4秒。这意味着:如果电梯从1楼到n楼不停地运行,成本为(n-1)*4秒。电梯停了10秒。因此,如果电梯停在每层楼,将花费(n-1)4+(n-2)10秒(不需要计算第n层的停车时间)。换句话说,工人上下一层楼需要20秒。他们从1楼走到n楼需要(n-1)20秒。显然,这不是一个好主意。所以有些人选择乘电梯去离办公室最近的楼层。
经过长时间的思考,哈尔终于找到了改善这种情况的方法。他告诉电梯员他的想法:首先,电梯员问人们想去哪层楼。然后,他将设计一个停车计划,尽量减少最后一个人到达办公室所在楼层的时间。例如,如果电梯需要在4楼、5楼和10楼停车,停车计划为:电梯在4楼和10层停车。因为电梯将在34=12秒到达4楼,然后停10秒,然后在34+10+64=46秒到达10楼。想去4楼的人将在12点到达他们的办公室
第二,想去5楼的人会在12+20=32秒到达,想去10楼的人将在46秒到达。因此,最后一个人到达办公室需要46秒。这对所有人来说都是一笔好交易。
现在,你应该编写一个程序来帮助电梯工作人员设计停车计划,从而最大限度地减少最后一个人到达楼层所需的时间。
输入
输入由几个测试用例组成。每个测试用例都在一行中,如下所示:
n f1 f2。。。fn
这意味着电梯总共需要停靠n层,n=0表示没有测试用例
再。f1 f2。。。fn是电梯停止的楼层(1<=n<=30000,2<=f1<=f2…fn<=30000)。每个数字之间用一个空格隔开。
输出
对于每个测试用例,在单行中输出最后一个阅读者所需的时间
样例输入
3 4 5 10
1 2
0
样例输出
46
4.
分析
电梯上一层楼需要4s,在一层楼停留10s,人上一层楼需20s。
现在需要设计一个算法,使得最后到达办公室的人所需的时间最短。
二分查找需要的最少时间t
判断t时间够不够用(贪心)
- 找到t时间内走不上去的层i,判断t时间内能到达(用电梯)。
- 不够用就否定该时间t,继续二分
- 推算出停靠层(如h层),可以走下去到达i层,还可以走上去到达新i层
- 停靠次数增加
总之充分发挥t时间,走上去走下去,削减层数
代码
#include <bits/stdc++.h>
using namespace std;
int n,//共停几层
tn,//顶层
vn,//实际停几层
v[30001];//实际停哪些层
bool k[30001];//需达哪些层
bool f(int t){//判断时间够不够
vn=0;memset(v,0,sizeof(v));//清空停层数据
for(int i=t/20+2;i<=tn;i++){//走上去需要20秒,t时间可达t/20层,所在层不算要+1
while(!k[i]&&i<tn)i++;//找到所需到达层
int t2=(i-1)4+vn10;//前面停靠次数10+电梯所需时间4(i-1)
if(t<t2)return 0;//用电梯直达的时间不够,则该方案取消。
//时间够
//电梯先达上h层,从h层走上去、走下去,尽量使用t时间
//t=(h-1)4+(h-i)20+vn10,电梯时间+走下来时间+停靠时间
//反推出h
int h=(t+20i-10vn+4)/24;
//实际停h层,在t时间内可以下到i层,也可以上到某一层,就是新的i
//t=(h-1)4+(i-h)20+vn10,反推出i 。注意停靠在h,是h-1
i=(t+16h-10vn+4)/20;
v[vn++]=h;//存下实际停靠层。注意不能vn++后再算新i
}
return 1;
}
int main(){
//freopen(“in.cpp”,“r”,stdin);
while(cin>>n&&n){
memset(k,0,sizeof(k));//清空
for(int i=0;i<n;i++){
int x;cin>>x;k[x]=1;tn=x;//记住顶层,需达哪些层
}
int l=0,m,r=(tn-1)*4+(tn-2)*10;//二分边界。r是极限需要时间,每层都停
while(l<=r){//二分找到所需最少时间
m=(l+r)/2;//
if(f(m))r=m-1;//时间充裕,可以缩短
else l=m+1;
}
cout<<l<<endl;//足够到达的最少时间
}
return 0;
}