编程之美之烙饼问题

来源:互联网 发布:电吉他 软件效果器 编辑:程序博客网 时间:2024/04/27 14:11
// 编程之美之一摞烙饼.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 他的程序确实有问题
	
				
		
原创粉丝点击