在高峰時間,實習生小飛常常會被電梯每層樓都停弄得很不耐煩,於是他想出了這樣一個辦法:由於樓層並不高,那麼在繁忙的時間,每次電梯從一層往上走時,我們只允許電梯停在其中的某一層。所有乘客都從一樓上電梯,到達某層樓後,電梯聽下來,所有乘客再從這裡爬樓梯到自己的目的層。在一樓時,每個乘客選擇自己的目的層,電梯則自動計算出應停的樓層。
問:電梯停在哪一層樓,能夠保證這次乘坐電梯的所有乘客爬樓梯的層數之和最少?
解法一:採用枚舉的方法 O(N^2)
#include<vector><br />#include<iostream><br />using namespace std;</p><p>int main(void)<br />{<br />int i,j,n,person,temp,ans,layer;<br />vector<int> num;<br />while(cin>>n) //表示n層數<br />{<br /> for(i=1;i<=n;i++)<br />{<br />cin>>person; //表示第幾層下電梯的人數<br />num.push_back(person);<br />}<br />ans=-1;<br />for(i=1;i<=n;i++)<br /> {<br />temp=0;<br />for(j=1;j<=n;j++)<br />{<br />if(i>=j)<br /> temp+=num[j-1]*(i-j);<br />else<br /> temp+=num[j-1]*(j-i);<br />}<br />if(ans==-1||temp<ans)<br />{<br />ans=temp;<br />layer=i;<br />}<br />}<br />cout<<"最少的層數: "<<ans<<endl;<br />cout<<"在第 "<<layer<<" 層下"<<endl;<br />}<br />return 0;<br />}
解法二:
線性演算法 O(n)
1:首先通過一次掃描計算第一層下所有乘客爬電梯的層數總和
2:然後通過每一層動態變化求得最後的結果
比如現在在第i層所有乘客爬電梯的層數總和為temp
在第i層下的有num1 在第i層的有num2 在第i層上的有num3
則如果在第i-1層下 temp+num3-num1-num2
如果在第i+1層下 temp+num1+num2-num3
#include<vector><br />#include<iostream><br />using namespace std;</p><p>int main(void)<br />{<br />int num1,num2,num3,i,n,ans,person,layer;<br />vector<int> num;<br />while(cin>>n)<br />{<br />vector<int> sum(n+2);<br />sum[0]=0;<br />ans=0;<br />num.push_back(0);<br />for(i=1;i<=n;i++)<br />{<br />cin>>person; //表示第幾層下電梯的人數<br />num.push_back(person);<br />sum[i]=sum[i-1]+num[i];<br />ans+=num[i]*(i-1);<br />}<br />//cout<<"ans="<<ans<<endl;<br />layer=1;<br />for(i=2;i<=n;i++)<br />{<br />num2=num[i-1];<br />num1=sum[i-1]-num2;<br />num3=sum[n]-sum[i-1];<br />if(num1+num2<num3)<br />{<br />ans=ans+num1+num2-num3;<br />layer=i;<br />}<br />}<br />cout<<"最少的層數: "<<ans<<endl;<br />cout<<"在第 "<<layer<<" 層下"<<endl;<br />}<br />}
解法二的改進:
#include<vector><br />#include<iostream><br />using namespace std;</p><p>int main(void)<br />{<br />int num1,num2,num3,i,n,ans,person,layer;<br />vector<int> num;<br />while(cin>>n)<br />{<br />ans=0;<br />num.push_back(0);<br />num3=0;<br />for(i=1;i<=n;i++)<br />{<br />cin>>person; //表示第幾層下電梯的人數<br />num.push_back(person);<br />ans+=num[i]*(i-1);<br />num3+=num[i];<br />}<br />//初始化<br />num2=num[1];<br />num3-=num2;<br />num1=0;<br />layer=1;</p><p>for(i=2;i<=n;i++)<br />{<br />if(num1+num2<num3)<br />{<br />ans=ans+num1+num2-num3;<br />layer=i;<br /> num1+=num2;<br />num2=num[i];<br />num3-=num[i];<br />//動態變化,編程技巧<br />}<br />else<br />break;<br />//這裡利用一個性質,最優的層數一定在中間,在他下面和上面的都比他要多<br />}<br />cout<<"最少的層數: "<<ans<<endl;<br />cout<<"在第 "<<layer<<" 層下"<<endl;<br />}<br />}