// 编程之美之一摞烙饼.cpp : 定义控制台应用程序的入口点。// 不同的程序会得到不同的结果吗?有个程序能得到不同的结果,但后来证明他的结果是错的//该算法有点在于在于找最少的交换次数,不是在于用最少的时间进行排序,此算法的排序时间不是最少的。因为算法的查找时间太长了。#include "stdafx.h"#include <iostream>#include <cstdlib>#include <Math.h>#include <assert.h>using namespace std;#define N 10//7class Cake{int nCakeNum;int *nCakeArr;//有用吗?int nMaxSwap;//实际进行的最大的交换次数int *nCakeResultArr;//存放在哪里进行了交换,存放的是编号int *nCakeReverseArr;//几乎所有的操作都是对它进行操作。int *nCakeReverseResultArr;//用来记录找到的结果int nSearch;public:Cake(){nCakeNum=0;nMaxSwap=0;nCakeArr=NULL;//没用吧nCakeResultArr=NULL;nCakeReverseArr=NULL;nCakeReverseResultArr=NULL;cout<<"in construst"<<endl;}~Cake()//析构函数自动运行,自动释放对象所占用的资源,不可以再用delete语句了(与编程之美书上不同)。{//if(nCakeArr!=NULL) delete nCakeArr;// if(nCakeResultArr!=NULL) delete nCakeResultArr;// if(nCakeReverseArr!=NULL) delete nCakeReverseArr;//if(nCakeReverseResultArr!=NULL) delete nCakeReverseResultArr;}void Run()//int *nCakeArr, int nCakeNum{//Init(nCakeArr,nCakeNum);//nSearch=0;Search(0);}void Output() const{for(int i=0;i<nMaxSwap;i++)cout<<nCakeReverseResultArr[i]<<" ";cout<<endl<<"最大的交换次数是:"<<nMaxSwap<<endl;cout<<"search times are :"<<nSearch<<endl;}void PrintArr(){for(int i=0;i<nCakeNum;i++)cout<<nCakeArr[i]<<" ";cout<<endl;}void PrintReverseArr(){for(int i=0;i<nCakeNum;i++)cout<<nCakeReverseArr[i]<<" ";cout<<endl;}void Init(int *pCakeArr, int pCakeNum){nSearch = 0;nCakeNum = pCakeNum;nCakeArr = new int[nCakeNum];assert(nCakeArr);for(int i=0;i<nCakeNum;i++)nCakeArr[i] = pCakeArr[i];//init 有用吗?nMaxSwap = UpperBound(nCakeNum);nCakeResultArr = new int[pCakeNum];assert(nCakeResultArr);nCakeReverseResultArr = new int[nMaxSwap];assert(nCakeReverseResultArr);nCakeReverseArr = new int[nCakeNum];assert(nCakeReverseArr);for(int i=0;i<nCakeNum;i++)nCakeReverseArr[i] = pCakeArr[i];//init}private:int UpperBound(int pCakeNum){return 2*(pCakeNum-2)+1;//原来是2*(pCakeNum-1) 改完这search times 由原来的715减少到589}int LowerBound(int *pCakeArr, int pCakeNum){int num=1;//应该是1.因为当最后一个不在其有序时对应的位置时,还要多翻转一次,当这由0改成1后,search times 由原来的4081减少到715for(int i=1;i<pCakeNum;i++){if((pCakeArr[i]-pCakeArr[i-1]==1)||(pCakeArr[i]-pCakeArr[i-1]==-1));elsenum++;}return num;}bool IsSorted(int *pCakeArr, int pCakeNum){for(int i=1;i<pCakeNum;i++){if(pCakeArr[i]<pCakeArr[i-1])return 0;}return 1;}void Reverse(int *nCakeReverseArr,int begin,int end)// operate nCakeReverseArr{int temp;assert(begin<end);for(int i=begin,j=end;i<j;i++,j--){temp=nCakeReverseArr[i];nCakeReverseArr[i]=nCakeReverseArr[j];nCakeReverseArr[j]=temp;}return;}void Search(int step){nSearch++;int estimate=LowerBound(nCakeReverseArr,nCakeNum);if(estimate+step>nMaxSwap||step>=nMaxSwap) //加后面的或语句运行次数4081,不加4129{return ;}if(IsSorted(nCakeReverseArr,nCakeNum)){if(step<nMaxSwap)//此算法找最少的翻转次数,不是最小的排序时间。解释:如果数组已经是有序的了,并且当前的步骤少于最大的翻转次数,更新当前的翻转次数,并把当前的结果记录下来。{nMaxSwap = step;for(int i=0;i<nMaxSwap;i++)nCakeReverseResultArr[i]=nCakeResultArr[i];//为什么用nCakeReverseResultArr?因为nCakeResultArr本函数返回后还会变,所以不能用其存储最后的结果}//若果当前的翻转次数没有原来的少,不更新,只是返回。return ;}for(int i=1;i<nCakeNum;i++){Reverse(nCakeReverseArr,0,i);nCakeResultArr[step]=i;//保存结果,记录从哪开始翻转的Search(step+1);Reverse(nCakeReverseArr,0,i);}return ;}};//myPizzaint _tmain(int argc, _TCHAR* argv[]){Cake cake1;//int arrb[N]={7,3,5,4,2,1,6};int arrb[N]={5,6,1,2,3,4,9,8,7,0};int *arr = new int[N];for(int i=0;i<N;i++){arr[i]=arrb[i];}cake1.Init(arr,N);cake1.PrintArr();cake1.Run();cake1.PrintReverseArr();//作为 递归的数组 遍历所有的分支 到最后没有变化 只是在遍历时把符合条件的存储起来cake1.Output();//cake1.PrintArr();delete [] arr;// 可以不用delete语句删除,不会报错system("pause"); return 0;}/*//1.3_pancake_1.cpp by flyinghearts#qq.com#include<iostream>#include<iomanip>#include<vector>#include<algorithm>using namespace std;class Pancake{ vector<int> cake; //当前各个烙饼的状态 vector<int> cake_swap; //每次翻转的烙饼位置 vector<int> result; //最优解中,每次翻转的烙饼位置 vector<int> cake_order; //第step+1次翻转时,翻转位置的优先顺序 int max_size; //预分配数组大小 int min_swap; //最优解的翻转次数 int min_swap_init; //最优解的翻转次数初始值 int count_search; //search_cake被调用次数 int count_reverse; //reverse_cake被调用次数 int cake_size; //要处理的烙饼数组大小 const int *cake_old; //要处理的原烙饼数组 bool not_turn_back; //是否允许翻回上一个状态 void search_cake(int size, int step, int least_swap_old); void reverse_cake(int index); //翻转0到index间的烙饼 Pancake(const Pancake&); Pancake& operator=(const Pancake&);public: Pancake(int size=0):max_size(0) { init(size); } void init(int size=0); void print() const; void process(); //显示最优解,翻转过程 int run(const int cake_arr[], int size, bool not_turn_back_=1, bool show=1);};void Pancake::init(int size){ if (size<=0) size=16; if (size>max_size){ max_size=size; cake.resize(size); cake_swap.resize(size*2); result.resize(size*2); cake_order.resize(size*size*2); } min_swap=0; min_swap_init=0; count_search=0; count_reverse=0; cake_size=0; cake_old=NULL; not_turn_back=true;}void Pancake::print() const{ if (min_swap>0){ if (not_turn_back) cout<< "turn back to last state: disallowed.\n"; else cout<< "turn back to last state: allowed.\n"; cout<< "minimal_swap initial: "<< min_swap_init<< " final: "<< min_swap << "\nsearch/reverse function was called: "<< count_search << "/"<< count_reverse<< " times\nsolution: "; for (int i=0;i<min_swap; ++i) cout<< result[i]<< " "; cout<< "\n\n"; }}void Pancake::process(){ if (min_swap>0 && cake_size>0 && cake_old != NULL){ cake.assign(cake_old, cake_old+cake_size); int i,j; const int WIDTH=3; cout<< "old: "; for (j=0; j<cake_size; ++j) cout<< setw(WIDTH)<< cake[j]<<" "; cout<<"\n"; for (i=0; i<min_swap; ++i){ reverse_cake(result[i]); cout<< setw(WIDTH)<< i+1<< "-"<< setw(WIDTH)<< result[i]<<": "; for (j=0; j<cake_size; ++j) cout<< setw(WIDTH)<< cake[j]<<" "; cout<<"\n"; } cout<<"\n\n"; }}void Pancake::reverse_cake(int index){ ++count_reverse; int *beg=&cake[0], *end=&cake[0]+index; int tmp; while(beg<end){ tmp = *beg; *beg++ = *end; *end-- = tmp; }}int Pancake::run(const int cake_arr[], int size, bool not_turn_back_, bool show){ count_search=0; count_reverse=0; min_swap=0; not_turn_back = not_turn_back_; cake_size=0; cake_old=NULL; if (cake_arr==NULL || size<=1) return 0; while (size>1 && size-1==cake_arr[size-1]) --size; //去除末尾已就位的烙饼 if (size<=1) return 0; if (size>max_size) init(size+16); cake.assign(cake_arr,cake_arr+size); cake_size=size; cake_old=cake_arr; int i, least_swap=0, sz=size-1, *p=&result[0]; while (sz>0){ //先计算一个可能解 for (i=0; i<=sz; ++i) if (cake[i]==sz) break; if (i!=0){ reverse_cake(i); *p++=i; //result.push_back(i); ++min_swap; } reverse_cake(sz); *p++=sz--; //result.push_back(sz); ++min_swap; while(sz>0 && sz==cake[sz]) --sz; } cake.assign(cake_arr,cake_arr+size); //恢复原来的数组 cake.push_back(size); //多放一个烙饼,避免后面的边界判断 cake_swap[0]=0; //为方便起见,假设第0步翻转的烙饼编号为0 for (i=0,least_swap=0; i<size; ++i) if (cake[i]-cake[i+1]+1u >2) least_swap++; //等同于if (cake[i]-cake[i+1]>1 || cake[i]-cake[i+1]<-1) least_swap++; min_swap_init=min_swap; if (least_swap != min_swap) search_cake(size,0,least_swap); if (show) print(); return min_swap;}void Pancake::search_cake(int size, int step, int least_swap_old){ ++count_search; while (size>1 && size-1==cake[size-1]) --size; //去除末尾已就位的烙饼 int least_swap=least_swap_old; for (int pos=1, last_swap=cake_swap[step++]; pos<size; ++pos){ if (not_turn_back && pos==last_swap) continue; //是否翻回上个状态 least_swap = least_swap_old ; if (cake[pos]-cake[pos+1]+1u<=2) ++least_swap; if (cake[0]-cake[pos+1]+1u<=2) --least_swap; if (least_swap+step >= min_swap) continue; cake_swap[step]=pos; if (least_swap == 0){ result.assign(&cake_swap[1],&cake_swap[1]+step+1); min_swap= step; return; } reverse_cake(pos); search_cake(size,step,least_swap); reverse_cake(pos); }}int main(){ //? int aa[10]={3,2,1,6,5,4,9,8,7,0}; int aa[6]= {3,5,2,6,1,4};//此时 改程序不对 Pancake cake(16); //? cake.run(aa,10); //? cake.run(aa,10,0); cake.run(aa,6); cake.run(aa,6,0); cake.process(); //遍历求第n个烙饼数 const int N=8; int i,j,max=0,tmp; int arr[N]; for (j=1;j<=N;++j){ for (i=0; i<j; ++i) arr[i]=i; max=0; while(next_permutation(arr,arr+j)){ tmp=cake.run(arr,j,1,0); if (tmp>max) max=tmp; } cout<<j<<" "<<max<<endl; }system("pause");}*/
http://blog.csdn.net/tianshuai11/article/details/7659673 他的程序确实有问题