一摞烙饼的排序问题--读书笔记(2)
生活随笔
收集整理的這篇文章主要介紹了
一摞烙饼的排序问题--读书笔记(2)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
問題描述:一摞大小不一的餅,由于一只手托著盤子,只好用另一只手,一次抓住最上面的幾塊餅,把它們上下顛倒個,反復幾次使烙餅安裝由小到大排好序。假設有n塊大小不一的餅,最少需要翻幾次使烙餅排好序。
分析與解法:
首先,經(jīng)過兩次翻轉(zhuǎn)可以把最大的烙餅翻轉(zhuǎn)到最下面,因此,最多需要把上面的n-1個烙餅依次翻轉(zhuǎn)兩次。那么至多需2(n-1)次翻轉(zhuǎn)就可以把所有烙餅排好序。當然還有更高效的方法,考慮每次翻轉(zhuǎn)的時候,把兩個本來應該相鄰的烙餅盡可能的換到一起,當所有的烙餅都換到一起時,實際上已經(jīng)完成了排序。因此,可以通過遞歸來進行求解。
遞歸的第一個退出條件是已經(jīng)排好序,還有就是翻轉(zhuǎn)次數(shù)多于2(n-1)就退出。在翻轉(zhuǎn)的過程中,可以看看當前的烙餅數(shù)組的排序情況如何,然后利用這些信息幫助減少翻轉(zhuǎn)次數(shù)。
每個狀態(tài)還應該有翻轉(zhuǎn)的最小次數(shù),這個下限值可以這樣確定:從最后一個位置開始,往前找到第一個與最終結果位置不同的烙餅編號(也就是說排除最后幾個已經(jīng)就位的烙餅),從該位置到第一個位置,計算相鄰的烙餅的編號不連續(xù)的次數(shù),再加上1。
代碼如下:
#include<stdio.h> #include<assert.h>class CPrefixSorting { public:CPrefixSorting(){m_nCakeCnt = 0;m_nMaxSwap = 0;}//計算烙餅翻轉(zhuǎn)信息//@param//pCakeArray 存儲烙餅索引數(shù)組//nCakeCnt 烙餅個數(shù)void Run(int* pCakeArray,int nCakeCnt){Init(pCakeArray,nCakeCnt);m_nSearch = 0;Search(0);}//輸出烙餅具體翻轉(zhuǎn)次數(shù)void Output(){for(int i = 0; i < m_nMaxSwap; i++){printf("%d", m_SwapArray[i]);}printf("\n |Search Times| : %d\n", m_nSearch);printf("Total Swap times = %d\n", m_nMaxSwap);}private:////初始化數(shù)組信息//@param//pCakeArray 存儲烙餅索引數(shù)組//nCakeCnt 烙餅個數(shù)//void Init(int* pCakeArray,int nCakeCnt){assert(pCakeArray != NULL);assert(nCakeCnt > 0);m_nCakeCnt = nCakeCnt;//初始化烙餅數(shù)組m_CakeArray = new int[m_nCakeCnt];assert(m_CakeArray != NULL);for(int i = 0; i < m_nCakeCnt; i++){m_CakeArray[i] = pCakeArray[i];}//設置最多交換次數(shù)信息m_nMaxSwap = UpBound(m_nCakeCnt);//初始化交換結果數(shù)組m_SwapArray = new int[m_nMaxSwap];assert(m_SwapArray != NULL);//初始化中間交換結果信息m_ReverseCakeArray = new int[m_nCakeCnt];for(int i = 0; i < m_nCakeCnt; i++){m_ReverseCakeArray[i] = m_CakeArray[i];}m_ReverseCakeArraySwap = new int[m_nMaxSwap];}////尋找當前翻轉(zhuǎn)的上界////int UpBound(int nCakeCnt){return (nCakeCnt) * 2;}////尋找當前翻轉(zhuǎn)的下界////int Lower_Bound(int* pCakeArray,int nCakeCnt){int t, ret = 0;//根據(jù)當前數(shù)組的排序信息情況來判斷最少需要交換多少次for(int i = 1; i < nCakeCnt; i++){//判斷位置相鄰的兩個烙餅,是否為尺寸排序上相鄰的t = pCakeArray[i] - pCakeArray[i-1];if((t == 1) || (t == -1)){}else{ret++;}}return ret;}// 排序的主函數(shù)void Search(int step){int i, nEstimate;m_nSearch++;//估算這次搜索所需要的最小交換次數(shù)nEstimate = Lower_Bound(m_ReverseCakeArray,m_nCakeCnt);if(step + nEstimate >= m_nMaxSwap)return;//如果已經(jīng)排好序,即翻轉(zhuǎn)完成,輸出結果if(IsSorted(m_ReverseCakeArray,m_nCakeCnt)){if(step < m_nMaxSwap){m_nMaxSwap = step;for(i = 0; i < m_nMaxSwap; i++)m_SwapArray[i] = m_ReverseCakeArraySwap[i];}return;}//遞歸進行翻轉(zhuǎn)for(int i = 1; i < m_nCakeCnt; i++){Revert(0, i);m_ReverseCakeArraySwap[step] = i;Search(step + 1);Revert(0, i);}}////true: 已經(jīng)排好序//false: 未排序//bool IsSorted(int* pCakeArray,int nCakeCnt){for(int i = 1; i < nCakeCnt; i++){if(pCakeArray[i-1] > pCakeArray[i]){return false;}}return true;}////翻轉(zhuǎn)烙餅信息//void Revert(int nBegin,int nEnd){assert(nEnd > nBegin);int i, j, t;//翻轉(zhuǎn)烙餅信息for(i = nBegin, j = nEnd; i < j; i++, j--){t = m_ReverseCakeArray[i];m_ReverseCakeArray[i] = m_ReverseCakeArray[j];m_ReverseCakeArray[j] = t;}} private:int* m_CakeArray; //烙餅信息數(shù)組int m_nCakeCnt; //烙餅個數(shù)int m_nMaxSwap; //最多交換次數(shù),根據(jù)前面的推斷,這里最多為m_nCakeCnt*2int* m_SwapArray; //交換結果數(shù)組int* m_ReverseCakeArray; //當前翻轉(zhuǎn)烙餅信息數(shù)組int* m_ReverseCakeArraySwap; //當前翻轉(zhuǎn)烙餅交換結果數(shù)組int m_nSearch; //當前搜索次數(shù)信息 };int main() {CPrefixSorting cpfs;int cakeArray[] = {3,2,1,6,5,4};cpfs.Run(cakeArray,6);cpfs.Output(); }
總結
以上是生活随笔為你收集整理的一摞烙饼的排序问题--读书笔记(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 办公技巧整合(不定时更新)
- 下一篇: 虚拟独享服务器,独享云虚拟主机和服务器