前兩個星期就看程式設計之美的一摞烙餅排序問題,剛開始看其**沒看懂什麼意思,後來看了人家的部落格才知道是怎麼回事了,自己寫了一遍其**做各種各樣的測試,嚇我一跳,乙個剪枝操作竟然省了那麼多的時間,想起上一道題的將帥問題,頓時讓我領悟到這程式設計之美的書籍,題目不但有意思,其**真的優雅和美,好了接下來看這個烙餅排序問題。
題目:
星期五的晚上,一幫同事在希格瑪大廈附近的「硬碟酒吧」多喝了幾杯。程式設計師多喝了幾杯之後談什麼呢?自然是演算法問題。有個同事說:「我以前在餐館打工,顧客經常點非常多的烙餅。店裡的餅大小不一,我習慣在到達顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由於我乙隻手托著盤子,只好用另乙隻手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反覆幾次之後,這摞烙餅就排好序了。我後來想,這實際上是個有趣的排序問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?」
你能否寫出乙個程式,對於n塊大小不一的烙餅,輸出最優化的翻餅過程呢?
程式設計之美的**:
class cprefixsorting
; //釋放陣列記憶體空間
virtual ~cprefixsorting()
;//最大的上界
int upperbound(int mcakecnt)
//最小的下界
int lowerbound(int *reversecake,int cakecnt )
else
}return reversecnt;
}//判斷烙餅是否排好序
bool issorted(int* reversecakearray,int cakecnt )
}return
true;
}//初始化資訊
void init(int * cakearray,int cakecnt)
//排序的核心函式
void search(int step)
if(issorted(mreversecakearray,mcakecnt))
//遍歷遞迴進行翻轉
for(int i=1;i//翻轉
reserver(0,i);
//儲存當前搜尋值對應翻轉月餅的索引
mreversecakearrayswap[step]=i;
//搜尋下乙個節點
search(step+1);
// printf("step:%d\n",step+1);
// for(int j=0;j//
// printf("\n");
//返回上一層
reserver(0,i);}}
//翻轉烙餅資訊
void reserver(int begin,int end)
}//執行函式介面
void run(int *cakearray,int cakecnt)
void output()
//輸出搜尋次數
printf("\n |search times : %d\n",msearch);
//輸出需翻轉最少的次數
printf("total swap times= %d\n",mmaxswap);
}private:
int * mcakearray;//儲存對應索引烙餅大小資訊陣列
int mcakecnt;//烙餅的個數
int mmaxswap;//烙餅的最大交換次數
int * mreversecakearray;//儲存當前翻轉後對應索引烙餅的大小資訊
int msearch; //當前搜尋次數
int * mreversecakearrayswap;//儲存當前對應搜尋值的被翻轉的烙餅索引
int * mswaparray;//儲存已經完全排好序的所有對應搜尋值得被烙餅索引
};#endif // cprefixsorting_h
int main()
; test.run(aa,3);
test.output();
}
執行結果:2 1
|search times : 19
total swap times= 2
剪枝操作的關鍵就是看其上界和下界兩個邊界,如果下界越大,上界越小其執行效率越高,測試:
修改上界值較大(調整更大的上界):
//最大的上界
int upperbound(int mcakecnt)
執行結果
2 1
|search times : 31
修改下界值較小(調整更小的下界)
lowcnt=-1;
執行結果:
2 1
|search times : 31
total swap times= 2
從結果可以看出,上界和下界的數值對其所搜次數的影響,這裡如果你傳入的陣列數目越多,影響會更明顯的,因為這裡涉及了一種搜尋樹的結構,該樹深度越高,樹的節點就越多,越密集那麼消耗的時間的次數就越高,這時利用分支限界法(即巧妙的利用邊界才停止其往下搜尋),控制搜尋深度,這樣就可以大大的減少時間效率了,如圖:
參考部落格:
一摞烙餅的排序(0621)
每乙個演算法都值得好好地分析 問題 假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最後大小有序的結果呢?這個排序問題非常有意思,首先我們要弄清楚解決問題的關鍵操作 單手每次抓幾塊餅,全部顛倒 每次我們只能選擇最上方的一堆餅,一起翻轉。而不能一張張地直接抽出來,然後進行插入,也不能交換任意兩塊餅子...
1 3 一摞烙餅的排序
一摞亂序擺放的烙餅,每次只能抓取最上面幾塊烙餅並翻轉,多次翻轉後能夠實現烙餅的從小到大 從上往下 的有序擺放。問題分析 這裡我們使用回溯法解決這個問題。直接用回溯法效率是低下的,因此要進行剪枝。這裡的剪枝條件是利用翻轉次數的上界和下界完成的。上界 4,2,1,5,3 5,1,2,4,3 3,4,2,...
1 3 一摞烙餅的排序
假設有n塊大小不一樣的烙餅,那麼最少要翻動幾次,才能達到最終有序的結果。思路 每次找到最大的然後從將最大的以及最大的上面的反轉,這時候最大的在最上面,然後將整個反轉,最大的就在最下面了。然後再對除了最下面的n 1個烙餅進行上述的操作,知道全部的烙餅有序。例如 13524 53124 42135 cl...