编程之美之小飞的电梯调度算法(多种解法)---Java语言
2018-01-28 11:16
531 查看
1.题目情景
我们假设都是从一楼上电梯的,而至于讯电梯停在其中的某一层。即所有的乘客都从一楼上电梯,到达某层之后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯则自动计算出应停的楼层,并且能够保证该层停使得所有乘客爬楼梯的层数之和最少。输入:第一行楼层数N,乘客人数n;第二行有n个数,表示乘客选择的目的层。
输出:输出为停止楼层和总共需要爬的楼梯。
2.解法一
第一种方法就是采取暴力求解的办法,采用双重循环的方式,外循环控制停的楼层,内循环计算当前楼层停,总共需要爬多少楼层,并保留最小值及其相应停电梯的楼层。具体代码如下:
package bianchengzhimei.part1_8; import java.util.*; public class ElevatorController { public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int n=sc.nextInt(); int passenger[]=new int ; for(int i=0;i<n;i++) { passenger[i]=sc.nextInt(); } int stopFloor=0; int minFloor=Integer.MAX_VALUE; for(int i=1;i<=N;i++)//控制停电梯的楼层 { int temp=0; for(int j=0;j<n;j++)//计算停在当前楼层,总共需要爬的楼层 { temp+=Math.abs(passenger[j]-i); } if(temp<minFloor) { minFloor=temp; stopFloor=i; } } System.out.println("最佳停电梯的楼层为:"+stopFloor); System.out.println("乘客需要爬楼梯的总数为:"+minFloor); sc.close(); } }运行结果如下:
10 6 4 8 3 9 10 5 最佳停电梯的楼层为:5 乘客需要爬楼梯的总数为:15这种方法比较简单直接,因此复杂度较高,为O(N*n),所以接下来我们想办法降低复杂度。如果n大于N,那么可以将上述程序做一些修改也可以稍微降低复杂度。当n大于N时,先计算N层楼每层楼有几个乘客,复杂度为O(n),然后再遍历,遍历过程复杂度为O(N*N),因此下面程序总复杂度为O(n+N*N)。
package bianchengzhimei.part1_8; import java.util.*; public class ElevatorController { public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int n=sc.nextInt(); int passenger[]=new in 4000 t[N+1]; for(int i=0;i<n;i++) { passenger[sc.nextInt()]+=1; } int stopFloor=0; int maxFloor=Integer.MAX_VALUE; for(int i=1;i<=N;i++)//控制停电梯的楼层 { int temp=0; for(int j=1;j<=N;j++)//计算停在当前楼层,总共需要爬的楼层 { temp+=Math.abs(j-i)*passenger[j]; } if(temp<maxFloor) { maxFloor=temp; stopFloor=i; } } System.out.println("最佳停电梯的楼层为:"+stopFloor); System.out.println("乘客需要爬楼梯的总数为:"+maxFloor); sc.close(); } }
3.解法二
我们假设停在第i层楼,那么当前楼层需要爬的总楼层是Y。如果有N1个乘客在楼层i以下,有N2个乘客在第i层楼,还有N3个乘客在第i层以上。那么如果现在电梯停在i-1层,则总共需要爬Y-N1+(N2+N3)层,如果改在i+1层,那么总共需要爬Y-N3+(N2+N1)层,所以我们可以换个思路,当电梯从一楼逐渐往上走的时候,当N2+N1-N3<0时,则继续往上爬,当当N2+N1-N3>=0,则可以停下来,因为往上爬的过程中N3是逐渐减小的,一旦N2+N1-N3>=0之后,那么随着楼层往上爬,这个差值会越来越大,即代表人们要爬的总楼层越来越多,所以当差值不再为负即可停下来。实现代码如下:
package bianchengzhimei.part1_8; import java.util.Scanner; public class ElevatorController2 { public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int n=sc.nextInt(); int Floor[]=new int[N+1];//用来统计每个楼层停下的人数 for(int i=0;i<n;i++) Floor[sc.nextInt()]+=1; sc.close(); int stopFloor=1;//先从第一层开始推算 int N1=0;//停在第一层的话,第一层是最低的,那么N1则为0 int N2=Floor[1];//假设第一次停在第一层,求出目标楼层是当前楼层的人数. //计算N3的初始值和停在1层对应的nMinFloor值 int N3=0; int nMinFloor=0; for(int i=2;i<=N;i++) { N3+=Floor[i]; nMinFloor+=Floor[i]*(i-1); } //然后逐渐往上走,寻找最优目标楼层。 for(int i=2;i<=N;i++) { if(N1+N2-N3<0)//即判断往上走,爬楼梯总数是否会减少。 { N1+=N2; N2=Floor[i]; N3-=Floor[i]; stopFloor=i;//更新停电梯楼层. nMinFloor+=(N1+N2-N3);//更新爬楼梯总数 } else break; } System.out.println("最佳停电梯的楼层为:"+stopFloor); System.out.println("乘客需要爬楼梯的总数为:"+nMinFloor); } }以上解法是从第一层往上走,依次更新相应的数据,直到目标值不能再优化时,得到最优值。运行结果如下:
10 6 4 8 3 9 10 5 最佳停电梯的楼层为:5 乘客需要爬楼梯的总数为:15
4.解法三
其实,还有一种解法,有n个乘客都有自己需要去的楼层,在停止楼层下电梯之后,大家都要去自己的目标楼层,那么我们假设每位乘客都已经在目的楼层了,那么我们可以将问题转换为,所有乘客在哪一层碰头,所需要爬的楼梯最少。一般这种会面算法,最佳地点应该选择在中间数,即将每一位乘客所在位置,放进一个数组并排序取中间数就是最佳会面地点。(注:当乘客数为n,则最佳地点就是有序地点集合中第(n+1)/2个元素代表的地点)。其中这里的排序可以用桶排序,因为楼层数不会过于庞大,那么把每一层都当做一个桶,然后把相应的人放进去,桶号即数组下标,然后逐个取出就完成了排序,复杂度是线性的。package bianchengzhimei.part1_8; import java.util.Scanner; public class ElevatorController3 { private static int[] calSort(int[] a,int N,int n) { int[] res=new int ; int k=0; for(int i=0;i<=N;i++) { int temp=a[i]; while(temp>0) { res[k++]=a[i]; } } return res; } public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int n=sc.nextInt(); int passenger[]=new int[N+1]; for(int i=0;i<n;i++) { passenger[sc.nextInt()]+=1; } sc.close(); int[] res=calSort(passenger,N,n);//桶排序 int stopFloor=res[(n+1)/2-1]; int nMinFloor=0; for(int i=1;i<=N;i++) { nMinFloor+=(i-stopFloor)*passenger[i]; } System.out.println("最佳停电梯的楼层为:"+stopFloor); System.out.println("乘客需要爬楼梯的总数为:"+nMinFloor); } }运行结果:
10 8 1 1 2 7 8 8 8 9 最佳停电梯的楼层为:7 乘客需要爬楼梯的总数为:22
相关文章推荐
- 编程之美--小飞--电梯调度算法 java实现
- 算法笔记_001:斐波那契数的多种解法(Java)
- Android支持Java语言语法编程 尚未承诺遵守规范
- Java语言程序设计-基础篇-编程练习4-18
- java语言编程模拟ATM自动取款机
- 《程序设计入门—Java语言.翁恺》第五周编程作业(2)-井字棋
- java语言的科学与艺术-编程练习4.14
- JAVA语言编程读取MAC地址
- 基础Java语言编程练习题
- Java程序语言(基础篇)第2章 基本程序设计 编程练习题解答
- 择摘from华为技术有限公司Java语言编程规范
- Java程序语言设计基础篇原书第十版第三章答案编程练习题
- java语言编程:求两个字符串的最大子串
- 基于Java语言的安卓程序编程之三HelloWorld程序解析
- 漫谈并发编程:Future模型(Java、Clojure、Scala多语言角度分析)
- 对于初学者学习Java语言的建议-Java基础-Java-编程开发
- Java 语言中的函数编程
- 黑马程序员 java语言网络编程概述
- 编程:用java 语言实现,输入一个数,就相应地输出的几维数组!||用1、2、2、3、4、5这六个数字,用java写一个函数,打印出所有不同的排列,要求:"4"不能在第三位,"3"与"5"不能相连