小飞的电梯调度算法

1、问题描述:

某大厦一共有6部电梯,在高峰时间,每层都有人上下,电梯在每层都停,实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法:由于楼层不太高,每次电梯往上走时,我们只允许电梯停在其中的某一层。所有乘客都从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯自动计算出相应的楼层。电梯应停在哪一层,能够保证这次乘坐电梯的所有乘客爬楼梯的层数之和最小?

2、分析:

该问题本质上是一个优化问题,从问题中我们可以看到,影响结果的主要有两个因素:乘客人数和电梯停的层数。假设楼层总共有N层,电梯停在x层,到第i层的乘客人数为Tot[i],则所爬楼梯的总数是:|x-1|*Tot[1]+|x-2|*Tot[2]+.....+|x-N|*Tot[N]。我们就是寻找一个最优的x,使总和最小。

3、解法:

<1>解法一

可以从第一层开始来枚举x,一直到第N层,然后计算出乘客所爬楼梯的总数,并求出最小值以及此时的x的值。这个算法的时间复杂度为O(n*n)。

#include <iostream>

using namespace std;

void min_floor(int floor_num,int tot_person[]);//参一:楼层总数;参二:去每层的人数

int main()
{
	int tot_person[7] = { 0,1, 2, 2, 0, 3, 2 };
	min_floor(6, tot_person);
}

void min_floor(int floor_num, int tot_person[])
{
	int i,j, minFloor,total_floor = 0, target_floor = -1;

	for (i = 1; i <= floor_num;i++)
	{
		for (j = 1; j <= i; j++)
			total_floor += tot_person[j] * (i - j);
		for (j = i + 1; j <= floor_num;j++)
			total_floor += tot_person[j] * (j - i);
		if (target_floor == -1 || minFloor > total_floor)
		{
			target_floor = i;
			minFloor = total_floor;
		}
		total_floor = 0;
	}
	cout << "目标楼层:" << target_floor << endl << "最少层数:" << minFloor << endl;
}
运行结果:

<2>解法二

假设电梯停在第i层楼,那我们可以计算出所有乘客爬的总楼层数Y。如果有N1个乘客目的楼层在i层楼以下,N2个乘客目的楼层在i层楼,N3个乘客在i层楼以上。在这种情况下,如果电梯改停在(i+1)层,那么目的楼层在i层以上的乘客将少爬一层,即N3个乘客将少爬N3层,目的楼层在i层及i层以下的乘客将多爬一层,及多爬(N1+N2)层,因此所有乘客爬的楼层数为Y-N3+N1+N2 = Y+(N1+N2-N3)。同理可以求的电梯改停在(i-1)层时,乘客所爬的楼层总数为Y-(N1-N2-N3)。由此可见当N1+N2 < N3时乘客少爬的楼层数为N3-N1-N2,电梯在i+1层停更好;如果N2+N3 < N1,乘客少爬的楼层数为N1-N2-N3,电梯停在i-1层更好;其它情况停在i层更好。

根据这个规律我们从第一层开始考察,计算乘客所爬楼梯的总数。然后再根据上面的策略进行调整,直到找到最佳楼层。总的时间复杂度为O(N)。

#include <iostream>

using namespace std;
void min_floor_second(int floor_num, int tot_person[]);//参一:楼层总数;参二:去每层的人数

int main()
{
	int tot_person[7] = { 0,1, 2, 2, 0, 3, 2 };
	min_floor_second(6,tot_person);
}

void min_floor_second(int floor_num, int tot_person[])
{
	int N1 = 0, N2 = tot_person[1], N3 = 0;
	int i, target_floor = 1,min_floor = 0;

	for (i = 2; i <= floor_num; i++)
	{
		N3 += tot_person[i];
		min_floor += tot_person[i] * (i - 1);
	}

	for (i = 2; i <= floor_num;i++)
	{
		if ( (N1 + N2) < N3)
		{
			target_floor = i;
			min_floor += (N1 + N2 - N3);
			N3 -= tot_person[i];
			N1 += N2;
			N2 = tot_person[i];
		}
		else
			break;
	}
	cout << "目标楼层:" << target_floor << endl << "所爬层数:" << min_floor << endl;
}
运行结果:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值