題目:一棟樓共N層,電梯每次從1層往上行走時只停其中的某一層,停止的依據是能夠保證這次乘坐電梯的所有乘客爬樓梯(向上或向下都行)的層數只和最少。
書中解法:
假設電梯停在第i層樓,此時所有乘客需要爬的樓梯層數總和為Y,其中有N1個人在i層以下,N2個人恰好在第i層,N3個人在i層以上。這是,如果電梯停在第i-1層,所有目的地在第i-1層以上的乘客需要多爬一層,共需多爬N2+N3層,而所有在第i層以下的乘客可以少爬一層,共可以少爬N1層。因此,此時乘客共需爬的層數總和為Y-N1+(N2+N3)= Y-(N1-N2-N3)。
反之,如果電梯在第i+1層停,那麼乘客共需爬的層數為Y+(N1+N2-N3)。因此,可見當N1>N2+N3時,電梯在i-1層停比較好,當N1+N2<N3時,電梯在i+1層停比較好,其他情況下電梯停在i層比較好。
根據這個規律,我們可以從第一層開始考察,計算各位乘客需要爬樓梯的數目。然後根據上面的策略進行調整,知道找到最佳樓層。總的時間複雜度為O(N)。
代碼如下:
# define N 5<br />void main()<br />{<br />int nPerson[] = {0,1,5,3,9,4};<br />int nMinFloor, nTargetFloor;<br />int N1, N2, N3;<br />nMinFloor = 0;<br />nTargetFloor = 1;<br />int i;<br />for(N1 = 0, N2 = nPerson[1], N3 = 0, i = 2; i <= N; i++)//calculate when the elevator stops at 1st floor, how many floors have to climb in total.<br />{<br />N3 += nPerson[i];<br />nMinFloor += nPerson[i] * (i - 1);<br />}<br />for(i = 2; i <= N; i++)<br />{<br />if(N1 + N2 < N3)<br />{<br />nTargetFloor = i;<br />nMinFloor += (N1 + N2 - N3);<br />N1 += N2;<br />N2 = nPerson[i];<br />N3 -= nPerson[i];<br />}<br />else<br />break;<br />}<br />cout << nMinFloor << endl << nTargetFloor << endl;<br />}
改進演算法:
通過分析,可以得出以下結論:假設到第i層的人數為Ni,那麼有下面的式子成立:
nTargetFloor = (totalfloors %totalpeople == 0)? (totalfloors / totalpeople) : (totalfloors / totalpeople +1);
其中totalfloor = 1*N1+2*N2+...i*Ni; totalpeople為乘坐此次電梯的總人數。
計算結果與書中一致,並且減少了求目標樓層時的計算時間。