日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

1.3一摞烙饼的问题

發布時間:2023/12/8 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 1.3一摞烙饼的问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目是這樣的:

星期五的晚上,一幫同事在希格瑪大廈附近的“硬盤酒吧”多喝了幾杯。程序員多喝了幾杯之后談什么呢?自然是算法問題。有個同事說:
“我以前在餐館打工,顧客經常點非常多的烙餅。店里的餅大小不一,我習慣在到達顧客飯桌前,把一摞餅按照大小次序擺好——小的在上面,大的在下面。由于我一只手托著盤子,只好用另一只手,一次抓住最上面的幾塊餅,把它們上下顛倒個個兒,反復幾次之后,這摞烙餅就排好序了。
我后來想,這實際上是個有趣的排序問題:假設有n塊大小不一的烙餅,那最少要翻幾次,才能達到最后大小有序的結果呢?


思想:

書上面給出的方法是通過遞歸尋找出最優方案。

遞歸結束條件有兩個:

1)遞歸步驟超過最大步驟數;

2)已經有序。

但由于遞歸過程步驟過多,需要對其進行剪枝:

1)定上界:假設每次只將最大的翻到最下面(跟冒泡類似),至多需要2次翻轉,總共有n-1個需要翻轉(最后一個不用翻了),那么最多需要2*(n-1)次翻轉;當然,為了減少更多不必要的遍歷,每次找到一個實現了有序的步驟數step,則將max更新為該step。

2)定下界:每次遞歸時,計算當前所在狀態下至少還需要多少次翻轉,設為lowerbound, 如果當前已經翻轉的步驟數step+lowerbound(已經翻轉步驟數+當前狀態下至少還需要的步驟數)超過了上界,則可以結束該次遞歸了。


代碼:

class CPrefixSorting { public:CPrefixSorting() {m_nCakeCnt = 0;m_nMaxSwap = 0;} ~CPrefixSorting() {if( m_CakeArray != NULL ) delete m_CakeArray;if( m_SwapArray != NULL ) delete m_SwapArray;if( m_ReverseCakeArray != NULL ) delete m_ReverseCakeArray;if( m_ReverseCakeArraySwap != NULL ) delete m_ReverseCakeArraySwap;}//pCakeArray 存儲烙餅索引數組//nCakeCnt 烙餅個數void Run(int *pCakeArray, int nCakeCnt) {Init(pCakeArray, nCakeCnt);m_nSearch = 0;Search(0);}// 輸出烙餅具體翻轉的次數void Output() {for(int i = 0; i < m_nMaxSwap; ++i) cout << m_SwapArray[i] << " ";cout << "Search times: " << m_nSearch;cout << "Total swap times: " << m_nMaxSwap;}private://pCakeArray 存儲烙餅索引數組//nCakeCnt 烙餅個數void Init(int* pCakeArray, int nCakeCnt) {assert( pCakeArray != NULL );assert( nCakeCnt > 0 );m_nCakeCnt = nCakeCnt;//初始化烙餅數組m_CakeArray = new int[nCakeCnt];assert( m_CakeArray != NULL );for(int i = 0; i < nCakeCnt; ++i) m_CakeArray[i] = pCakeArray[i];//設置最多交換次數信息m_nMaxSwap = UpperBound(m_nCakeCnt);//初始化交換結果數組m_SwapArray = new int[m_nMaxSwap + 1];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];}//尋找當前翻轉的上界int UpperBound(int nCakeCnt) { return nCakeCnt * 2; }//尋找當前翻轉的下界int LowerBound(int* pCakeArray, int nCakeCnt) {int ret = 0;//根據當前數組的排序信息情況來判斷最少需要交換多少次for(int i = 1; i < nCakeCnt; ++i) {//判斷位置相鄰的兩個烙餅,是否為尺寸排序上相鄰的int t = pCakeArray[i] - pCakeArray[i-1];if(t == 1 || t == -1) { }else ++ret;}return ret;}void Search(int step) {m_nSearch++;//估算這次搜索所需要的最小交換次數int nEstimate = LowerBound(m_ReverseCakeArray, m_nCakeCnt);if( step + nEstimate > m_nMaxSwap ) return ;//如果已經排好序,即翻轉完成,輸出結果if( IsSorted(m_ReverseCakeArray, m_nCakeCnt) ) {if( step < m_nMaxSwap) {m_nMaxSwap = step;for(int i = 0; i < m_nMaxSwap; ++i) m_SwapArray[i] = m_ReverseCakeArraySwap[i];}return ;}//遞歸進行翻轉for(int i= 1; i < m_nCakeCnt; ++i) {Reverse(0, i);m_ReverseCakeArraySwap[step] = i;search(step + 1);Reverse(0, i);}}bool IsSorted(int* pCakeArray, int nCakeCnt) {for(int i = 1; i < nCakeCnt; ++i) {if(pCakeArray[i-1] > pCakeArray[i]) return false;}return true;}//翻轉烙餅信息void Reverse(int nBegin, int nEnd) {assert( nBegin < nEnd );//翻轉烙餅信息for(int i = nBegin, j = nEnd; i < j; ++i, --j) {int temp = m_ReverseCakeArray[i];m_ReverseCakeArray[i] = m_ReverseCakeArray[j];m_ReverseCakeArray[j] = temp;}}private:int* m_CakeArray; //烙餅信息數組int m_nCakeCnt; //烙餅個數int m_nMaxSwap; //最多交換次數,根據前面的推斷,這里最多為m_nCakeCnt*2int* m_SwapArray; //交換結果數組int* m_ReverseCakeArray; //當前翻轉烙餅信息數組int* m_ReverseCakeArraySwap; //當前翻轉烙餅交換結果數組int m_nSearch; //當前搜索次數信息 };


#include <iostream> using namespace std;#define NMAX 1000int UpperBound(int nCakeCnt); void Search(int step); int LowerBound(int* nCakeArray, int nCakeCnt); bool IsSorted(int* nCakeArray, int nCakeCnt); void Reverse(int nBegin, int nEnd);int nCakeCnt; //存儲月餅的個數 int nCake[NMAX]; //存儲月餅的半徑 int nReverseCakeArray[NMAX]; //翻月餅的過程,中間結果 int nMaxSwap = UpperBound(nCakeCnt); //最多翻轉的次數 int nReverseCakeArraySwap[NMAX]; //每次翻轉一次,都記錄在這個數組中 int totalAns = 0; //總的翻轉的次數 int nSwapArray[NMAX]; //void Search(int step) {totalAns++;int nEstimate = LowerBound(nReverseCakeArray, nCakeCnt);if(step + nEstimate > nMaxSwap) return ;if(IsSorted(nReverseCakeArray, nCakeCnt)) {if(step < nMaxSwap) {nMaxSwap = step;for(int i = 0; i < nMaxSwap; ++i) nSwapArray[i] = nReverseCakeArraySwap[i];}return ;}for(int i = 1; i < nCakeCnt; ++i) {Reverse(0, i);nReverseCakeArraySwap[step] = i;Search(step + 1);Reverse(0, i);} }int UpperBound(int nCakeCnt) {return 2 * nCakeCnt; }int LowerBound(int* nCakeArray, int nCakeCnt) {int ret = 0;for(int i = 1; i < nCakeCnt; ++i) {int t = nCakeArray[i] - nCakeArray[i-1];if(t == 1 || t == -1) {}else ++ret;} return ret; }bool IsSorted(int* nCakeArray, int nCakeCnt) {for(int i = 1; i < nCakeCnt; ++i) if(nCakeArray[i] < nCakeArray[i-1]) return false;return true; }void Reverse(int nBegin, int nEnd) {for(int i = nBegin, j = nEnd; i < j; ++i, --j) {int temp = nReverseCakeArray[i];nReverseCakeArray[i] = nReverseCakeArray[j];nReverseCakeArray[j] = temp;} }int main() {cin >> nCakeCnt;for(int i = 0; i < nCakeCnt; ++i) {cin >> nCake[i];nReverseCakeArray[i] = nCake[i];}Search(0);cout << totalAns << endl; }


總結

以上是生活随笔為你收集整理的1.3一摞烙饼的问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。