小數學解決大問題
前言
最近閱讀了Google黑板報的“數學之美”系列文章,加上最近工作和學習中接觸了不少的演算法最終都是由簡單的數學公式或者定理解決了問題。我突發奇想地希望將我所知道的數學巧妙運用解決問題的例項記錄下來。因此這篇部落格誕生了,也希望我能夠逐步地完善,並且寫出一個系列的文章。話不多說,這篇文章就從引發我寫下這篇部落格的問題入手。
切餅問題
問題描述
假設我們有一個圓形的餅和一把刀。由於刀比較珍貴,刀的主人比較愛惜,因此要求我們儘可能的少用這把刀。但是我們希望能夠將餅分給更多的人。總而言之,問題可以描述成,有這把刀沿直線在餅上切n刀,求出切完後餅的最大塊數R[n]。
問題思路
要想解決這個問題首先,我們需要思考一些特例來得出一定的規律。如下圖所示,第一刀只能將餅分為兩塊;第二刀可以與第一刀相交,並且將餅分為4塊;以此類推第n刀可以與前n-1刀相交。有了以上這個粗略的思路,我們需要額外的幾個問題需要考慮或者證明:
1)是否第n刀總能與第n-1刀相交?由於線與線之間只有兩種狀態,即平行或相交。同時, 相交的直線通過平移之後依然相交。所以我們可以通過平移相交的直線使之與餅內部相交。
2)已經切n-1刀以後,第n刀如何切割可以增加最多的塊數。簡單來說,我們是這尋找一條直線,通過這條直線的餅的子塊最多。由於我們證明了第n刀可以和前n-1刀相交,而且顯然只能各相交一次。前n-1刀在餅上某出最多可以分割出n-1+1塊子塊。
回答了以上的問題,我們就可以列出整個遞迴的規律了。
切割次數 | 最大子塊個數 | 餅中某條直線上存在的最大子塊數 |
0 | 1 | 1 |
1 | 2 | 2 |
2 | 4 | 3 |
3 | 7 | 4 |
4 | 11 | 5 |
5 | 16 | 6 |
用數學的表示式表示出來即,
最大子塊個數用max_piece[n]表示,餅中某條直線上存在的最大子塊數用max_piece_in_line[n]表示。非常容易推出通項公式為
max_piece[n]=max_piece[n-1] + max_piece_in_line[n-1]
max_piece_in_line[n] = n+1;
顯然,我們已經可以通過遞迴或者動態規劃的方式獲得我們希望的答案。但是正如我前言中提到的,許多問題其實是能夠有更加巧妙的數學方法的。因此,我們可以進一步的研究這個問題的數學通項公式。我們通過消除max_piece_in_line得:
max_piece[n]=max_piece[n-1] + n
進行簡單變換,求出另一通項公式為:
a[n] = max_piece[n] - max_piece[n-1]=n
所以,a[n]+a[n-1]+...+a[1] = n+n-1+...+1 = (n+1)*n/2。並且a[n]+a[n-1]+...+a[1]=(max_piece[n] - max_piece[n-1]) + (max_piece[n-1] - max_piece[n-2]) +...+ (max_piece[1] - max_piece[0]) = max_piece[n] - max_piece[0]
因此,max_piece[n] - max_piece[0] = (n+1)*n/2。綜上所述,max_piece[n] = (n+1)*n/2 + 1。