电梯调度问题

电梯调度问题

实际需求是这样的,电梯之前是在一楼,然后跑来一波研究僧,分别是到达不同的实验室。

实验室分别是坐落在2楼至5楼。假设电梯是个巨无霸,容量是无穷的(实际上老逸夫楼那个

估计已经年久失修,已经扛不住多少人了),然后某天,就假设是苦逼的星期一吧,依旧是

一波研究僧要乘坐电梯,但是电梯星期一都是比较古怪的(只限于星期一),它只在其中的

一层停下来,然后各层的研究僧只能下电梯,然后爬苦逼的楼梯到达各自的实验室。问题是

要给出一种解决方案电梯在哪层停使得这些苦逼的研究僧们爬楼梯的层数最少。

解题思想:

问题抽象为:

到达各自楼层的人数分别是A[1],A[2],A[3],A[4],A[5],当然一楼的GGMM们可以不乘电梯,爬楼数固定为0啊

假设电梯停在第i层,则不同的淫可以分为三类,

第一类就是实验室在i层,第二类实验室在i层下面,第三类是实验室在i层之上。这样我们可以穷举电梯所停的可能性

然后判断对应的研究僧的爬楼层数,从而可以找出一个最好的解决方案。这样解决方案,还是O(N^2)

实际上我们可以在O(N)的时间内解决此问题。

对于电梯所停的每一层比如i层,N1在i层,N2在i层上,N3在i层下。电梯如果再网上上一层,则爬楼数应该-N2+N1+N3,

也就是在一楼的时候可以初始化这三个变量,然后判断(N1+N3-N2)是否是大于零,若是大于零则不可取啊,若是小于零

可以更新电梯所听的层啊。。。这样扫描一次就ok了。。。

在高峰时间,实习生小飞常常会被电梯每层楼都停弄得很不耐烦,于是他想出了这样一个办法:由于楼层并不高,那么在繁忙的时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有乘客都从一楼上电梯,到达某层楼后,电梯听下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼时,每个乘客选择自己的目的层,电梯则自动计算出应停的楼层。

问:电梯停在哪一层楼,能够保证这次乘坐电梯的所有乘客爬楼梯的层数之和最少?

解题程序:

解法一:采用枚举的方法 O(N^2)

 

  1. #include<vector> 
  2. #include<iostream> 
  3. using namespace std; 
  4.  
  5. int main(void
  6.     int i,j,n,person,temp,ans,layer; 
  7.     vector<int> num; 
  8.     while(cin>>n)  //表示n层数 
  9.     { 
  10.     for(i=1;i<=n;i++) 
  11.     { 
  12.         cin>>person;    //表示第几层下电梯的人数 
  13. num.push_back(person);
  14.     } 
  15.     ans=-1; 
  16.     for(i=1;i<=n;i++) 
  17.     { 
  18.         temp=0; 
  19.         for(j=1;j<=n;j++) 
  20.         { 
  21.         if(i>=j) 
  22.         temp+=num[j-1]*(i-j); 
  23.         else 
  24. temp+=num[j-1]*(j-i);
  25.         } 
  26.         if(ans==-1||temp<ans) 
  27.         { 
  28.             ans=temp; 
  29.             layer=i; 
  30.         } 
  31.     } 
  32.     cout<<"最少的层数: "<<ans<<endl; 
  33.     cout<<"在第 "<<layer<<" 层下"<<endl; 
  34.     } 
  35.     return 0; 

解法二:

线性算法 O(n)
1
:首先通过一次扫描计算第一层下所有乘客爬电梯的层数总和

2
:然后通过每一层动态变化求得最后的结果
比如现在在第i层所有乘客爬电梯的层数总和为temp
在第i层下的有num1在第i层的有num2在第i层上的有
num3
则如果在第i-1层下
temp+num3-num1-num2
如果在第i+1层下temp+num1+num2-num3

1. #include<vector>

2. #include<iostream>

3. usingnamespace std;

4.  

5. int main(void)

6. {

7. intnum1,num2,num3,i,n,ans,person,layer;

8. vector<int> num;

9. while(cin>>n)

10.{

11.ans=0;

12.num.push_back(0);

13.num3=0;

14.for(i=1;i<=n;i++)

15.{

16.cin>>person;//表示第几层下电梯的人数

17.num.push_back(person);

18.ans+=num[i]*(i-1);

19.num3+=num[i];

20.}

21.//初始化

22.num2=num[1];

23.num3-=num2;

24.num1=0;

25.layer=1;

26. 

27.for(i=2;i<=n;i++)

28.{

29.if(num1+num2<num3)

30.{

31.ans=ans+num1+num2-num3;

32.layer=i;

33.num1+=num2;

34.num2=num[i];

35.num3-=num[i];

36.//动态变化,编程技巧

37.}

38.else

39.break;

40.//这里利用一个性质,最优的层数一定在中间,在他下面和上面的都比他要多

41.}

42.cout<<"最少的层数: "<<ans<<endl;

43.cout<<"在第 "<<layer<<"层下"<<endl;

44.}

45.}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值