一栋楼房有一电梯,居民进入楼梯后按一楼层,假设电梯只能停在某一层,问怎么样停靠使得居民爬楼梯的总和最小?
或者可以抽象为给定一个数组,数组中数字大小代表元素个数,在数组中选定一个位置,使得数组所有元素到该位置的距离最小
关键思路:
设第i层当前人数为C1,到该楼层下的人有M个,需要爬楼总和M1,到该楼层以上的人有N个,需要爬楼总和N1
那么当到i+1层后,设该层人数为C2
到该楼层下的人有M+C1个,需要爬楼总和M1+C1,到该楼层以上的人有N-C2个,需要爬楼总和N1-N
简单点说,就是电梯每上一层,楼下的所有人要多爬一层,楼上的人要少爬一层,这样计算的时候只要在上一层的状态下进行运算即可,不用每次都把到所有楼层的距离计算一遍。
实现如下:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int length;
cin>>length;
cout<<"数组长度为"<<length<<endl;
int *p=new int[length];
for(int i=0;i<length;i++)
p[i]=0;
int floor,num=0;
cin>>floor;
while(floor)
if(floor>0&&floor<=length)
{
num++;
p[floor-1]+=1;
cin>>floor;
}
cout<<"一共有"<<num<<"位乘客"<<endl;
for(int i=0;i<length;i++)
cout<<setw(3)<<i+1;
cout<<endl;
for(int i=0;i<length;i++)
cout<<setw(3)<<p[i];
cout<<endl;
int below,current,above=0; //分别记录目的的为当前楼层以下(A1),当前楼层,当前楼层以上的总人数(A2)
int Lbelow,Labove=0; //对应上面集合中A1,A2的人需要爬的楼梯总数
int min=0,perfectfloor=0; //记录动态的最小爬楼梯和以及对应楼层
Lbelow=below=0;
current=p[0];
for(int i=1;i<length;i++)
{
above+=p[i];
Labove+=p[i]*i;
}
min=Labove;
for(int i=1;i<length;i++)
{
below+=p[i-1];
Lbelow+=below;
Labove-=above;
above-=p[i];
if(Labove+Lbelow<min)
{
min=Labove+Lbelow;
perfectfloor=i;
}
}
cout<<"最佳停靠楼层为"<<perfectfloor+1<<endl;
}
结果: