问题描述: 有一摞烙饼,因为一只手端着盘子,所以只能用另外一只手来给烙饼排序,将烙饼由大到小排好序。这样就要求我们在给烙饼排序的时候总是将最上面的N个烙饼一起翻转。如果最下面的烙饼是最大的,那么只需要解决上面的N-1个烙饼,同理可以最后到解决两个烙饼的排序。
简单的排序方法:先找到最大的烙饼,将其和其以上的烙饼一起翻转,这样最大的烙饼就在盘子的最上面了,然后翻转所有的烙饼,这样最大的烙饼就在盘子的最下面了。同样的,处理剩下的N-1个烙饼,知道最后所有的烙饼都排好序。可以知道我们最多需要进行2*(N-1)次翻转就可以将所有的烙饼排好序。
问题? 如果减少烙饼的反转次数,达到一个最优的解。 加入这堆老兵中有几个不同的部分相对有序,凭直接来猜测,可以把笑一下的烙饼进行翻转,每次考虑翻转烙饼的时候总是把相邻的烙饼尽可能的放到一起。
解决方法: 通过穷举法来找所有可能方案中的最优方案,自然会用到动态规划或者递归的方法来实现。可以从不同的翻转策略开始,比如第一次先翻最小的,然后递归的把所有的可能都全部翻转一次。
既然2(N-1)是一个最多的翻转次数,就可以得知,如果算法中的翻转次数超过了2(N-1),我们就应该放弃这个算法。
/*
* Sorting.cpp
*
* Created on: 2014年2月7日
* Author: Eileen
*/
#include "Sorting.h"
#include <stdio.h>
#include <assert.h>
#include <iostream>
using namespace std;
Sorting::Sorting(){
// TODO Auto-generated constructor stub
m_nCakeCnt = 0;
m_nMaxSwap = 0;
}
Sorting::~Sorting() {
// TODO Auto-generated destructor stub
}
void Sorting::Init(int* pCakeArray, int nCakeCnt){
assert(pCakeArray!=NULL);
assert(nCakeCnt > 0);
m_nCakeCnt = nCakeCnt;
m_CakeArray = new int[m_nCakeCnt];
assert(m_CakeArray !=NULL);
for(int i=0; i<m_nCakeCnt; i++)
{
m_CakeArray[i] = pCakeArray[i];
}
//设置最多交换次数信息
m_nMaxSwap = UpBound(m_nCakeCnt);
//初始化交换结果数组
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];
}
int Sorting::UpBound(int nCakeCnt){
return nCakeCnt*2;
}
int LowerBound(int* pCakeArray, int nCakeCnt){
int t, ret = 0;
//根据当前数组的排序信息情况来判断最少需要交换多少次
for(int i=1; i<nCakeCnt; i++)
{
t = pCakeArray[i] - pCakeArray[i-1];
if((t == 1) || (t == -1))
{
}
else
{
ret++;
}
}
return ret;
}
bool Sorting::IsSorted(int* pCakeArray, int nCakeCnt)
{
for(int i=1; i<nCakeCnt; i++)
{
if(pCakeArray[i-1] > pCakeArray[i])
{
return false;
}
}
return true;
}
void Sorting::Revert(int nBegin, int nEnd){
assert(nEnd > nBegin);
int i, j, t;
for(i = nBegin, j=nEnd; i<j; i++, j--)
{
t = m_ReverseCakeArray[i];
m_ReverseCakeArray[i] = m_ReverseCakeArray[j];
m_ReverseCakeArray[j] = t;
}
}
//排序的主函数
void Sorting::Search(int step){
int i, nEstimate;
m_nSearch++;
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(i = 0; i<m_nMaxSwap; i++)
m_SwapArray[i] = m_ReverseCakeArraySwap[i];
}
return;
}
for(i=1; i<m_nCakeCnt; i++)
{
Revert(0,i);
m_ReverseCakeArraySwap[step] = i;
Search(step+1);
Revert(0,i);
}
}
void Sorting::Run(int* pCakeArray, int nCakeCnt)
{
Init(pCakeArray, nCakeCnt);
m_nSearch = 0;
Search(0);
cout<< m_nMaxSwap <<endl;
for(int i=0; i<m_nMaxSwap; i++)
cout<< m_SwapArray[i];
}