电梯调度编程
题目
一栋10层的大楼(楼层编号1-10),设有一台无限载重的电梯,初始时电梯停在1层。电梯移动1层的耗时为1,在某一层停靠的耗时为1(时间初始为0)。为了使得乘客等待的时间(电梯在目的层的停靠时刻 - 乘客发出请求时刻)总和最小,请你编写一个程序来进行电梯调度。
输入有5个请求,每个请求一行,格式为请求时刻 起始楼层数 去往方向,其中方向为0代表向上去往10层,为1代表向下去往1层。
输出每次对应的决策,每一行的输出格式为xx时,停靠在x楼。其中,“xx时刻”指的是在某层楼停靠的时刻,且不算入在该层的停靠时间。如:
1.当0时刻时,电梯此时在1层,输入有0 1 0,那么电梯从1层接客(1s)前往10层(9s),应输出10时,停靠在10楼(1+9=10)。此时,该乘客等待时间为(10-0=)10。
2.当0时刻,电梯此时在1层,输入有0 2 0,那么电梯从1层前往2层(1s),接上乘客(1s),前往10层(8s),应输出10时,停靠在10楼(1+1+8=10)。此时,该乘客等待时间为(10-0=)10s。
最后输出完成5个请求(所有乘客都到达目的地)后,各乘客的等待时间总和。
要求
请自己设计5组测试用例,且具有一定代表性,用以验证程序是否是最小耗时。
编程语言选择C或C++都可以,但需要符合编码规范,且必须要有注释。要求在github上建立一个仓库,将本次作业代码提交到该仓库,并在博客开头给出仓库地址。注意:commit信息要遵守一定的git规范(可参看:git commit 规范指南),git必须使用命令行操作,不要使用github图形界面(可参看:廖雪峰Git教程)。
写一篇博客,在博客中描述在编码过程中,程序的不断优化过程。并列出一张表格,记录编写程序的代码行数、调试的bug数 、完成该次作业总耗时。
思路
引入时间变量time记录总时间,运行到每个点判断向上和向下的请求数并执行较大者(向下的请求数=目标为1楼的请求个数+此时电梯下方未上电梯的请求个数,向上的请求数同理。当某一请求的请求时刻>time或已经登上电梯时,该请求不纳入计算。),每次运行到请求点或目的地时再执行判断,直到所有乘客都到达目的地。
实现方式
把5个请求(a,b,c)输入到结构体变量数组request[5]中,并按起始楼层从低到高将数组排序。
代码1.0(不完满)
#include<stdio.h>
int main()
{
struct request
{
int a; int b; int c;
}
request[5],temp;//定义结构体数组request和变量temp,用于于存入请求和暂存排序交换。
int i,j,down=0,up=0,time=0,sum_c=0,t[20],f[20],un_down=0,un_up=0,down_ac,up_ac,down_to_1=0,up_to_10=0,above=0,below=0,ac=0,f_now;
//a[20]用来存目标楼层
for(i=0;i<5;i++)
scanf("%d%d%d",&request[i].a,&request[i].b,&request[i].c);//输入5个请求赋值到结构体变量数组中 。
for(i=1;i<5;i++)
{
sum_c+=request[i].c;
if(request[i].b<request[i-1].b)
{
temp=request[i];request[i]=request[i-1];request[i-1]=temp;
}//按起始楼层从低到高排序数组。
}
for(time=0; ;time++)
{ for(i=0;i<5;i++)
{
if(request[i].b!=0)
{
if(request[i].b<f_now)
below++;//below记录此时电梯下方且未上电梯的请求个数
else
above++;//above记录此时电梯上方且未上电梯的请求个数
}
}
down=sum_c+below;//向下的请求数=目标为1楼的请求个数+此时电梯下方且未上电梯的请求个数
up=5-sum_c+5-below;//向下的请求数=目标为10楼的请求个数+此时电梯上方且未上电梯的请求个数
for(ac=1;;)
{
if(down>=up)
{
if(i==0)
f_now=1;
else
f_now=request[i-1].b;
if(f_now==1)
for(i=0;i<5;i++)
if(request[i].c==1)
{
request[i].b=0;down_to_1=1;//down_to_1=1表示向下到一楼的乘客已经到达
}
}
else
{
if(i=4)
f_now=10;
else
f_now=request[i+1].b;
if(f_now==10)
for(i=0;i<5;i++)
if(request[i].c==10)
{
request[i].b=0;up_to_10=1;
}
}
for(j=0;j<5;j++)
if(request[j].b==f_now)
{
t[ac]=time;f[ac]==f_now;ac++;//ac记录电梯第几次停靠,t[ac]记录停靠时间,f[ac]记录停靠楼层
}
}
if(down_to_1==1&&up_to_10==1) break;
}
for(i=1;i<ac;i++)
printf("%d时,停靠在%d楼",t[ac],f[ac]);
return 0;
}
历史思路(bug之路)
1.从电梯有几种运行路线出发,分为不回头,回头一次,回头两次...结果发现情况太复杂,判断条件太难写,不可实现就舍弃了。
2.从逆向考虑,问题相当于电梯在一楼先载上所有人,然后再逐个卸下。然后最后发现并不能使问题简单化。
待优化:
1.把一些函数从主函数中剥离出来,降低代码的耦合度
2.代码还未完成,有很多bug
3.还未建立git库