亚洲微软研究院所在的希格玛大厦一共有6部电梯。在高峰时间,每层都有人上下,电梯每层都停。实习生小飞常常会被每层都停的电梯弄的很不耐烦,于是他提出了这样一个办法:
由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯则计算出应停的楼层。
由于楼层并不算太高,那么在繁忙的上下班时间,每次电梯从一层往上走时,我们只允许电梯停在其中的某一层。所有乘客从一楼上电梯,到达某层后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层。在一楼的时候,每个乘客选择自己的目的层,电梯则计算出应停的楼层。
问:电梯停在哪一层楼,能够保证这次乘坐电梯的所有乘客爬楼梯的层数之和最少?
1)暴力枚举法O(n)
int f(int person[], int N){//枚举法
int targetFloor=0;
int minFloors=INT_MAX;//int型最大值0x7fffffff
for(int i=1;i<=N;++i){
int sumFloors=0;
for(int j=1;j<=N;++j){
sumFloors+=person[j]*abs(i-j);//<span style="font-family: Arial, Helvetica, sans-serif;">person[j]表示要在j层下的人数</span>
}
if(sumFloors<minFloors){
minFloors=sumFloors;
targetFloor=i;
}
}
return targetFloor;
}
2)dp,由下往上O(n)
int f1(int person[], int N){//dp
int targetFloor=1;
//N1个乘客在i楼以下楼层下,N2个乘客在i楼层下,N3个乘客在i楼层以上楼层上
int N1=0;
int N2=person[1];
int N3=0;
int sumFloors=0;
for(int i=2;i<=N;++i){
N3+=person[i];
sumFloors+=person[i]*abs(i-1);
}
for(int i=2;i<=N;++i){
if(N1+N2<N3){
sumFloors+=(N1+N2-N3);//y(i+1)=y(i)+N1+N2-N3.
targetFloor=i;
N1+=N2;
N2=person[i];
N3-=N2;
}
else{
break;
}
}
return targetFloor;
}
3)dp, 由上往下O(n)
int f2(int person[], int N){//dp
int targetFloor=N;
//N1个乘客在i楼以下楼层下,N2个乘客在i楼层下,N3个乘客在i楼层以上楼层上
int N1=0;
int N2=person[N];
int N3=0;
int sumFloors=0;
for(int i=1;i<=N-1;++i){
N1+=person[i];
sumFloors+=person[i]*abs(i-N);
}
for(int i=N-1;i>=1;--i){
if(N3+N2<N1){
sumFloors+=(N3+N2-N1);//y(i-1)=y(i)+N3+N2-N1.
targetFloor=i;
N3+=N2;
N2=person[i];
N1-=N2;
}
else{
break;
}
}
return targetFloor;
}
测试
int main(){
int person[6]={0,1,3,2,3,1};
cout<<f(person,5)<<endl; //注意这里数组是从i=1开始的
return 0;
}