// 编程之美之一摞烙饼.cpp : 定义控制台应用程序的入口点。
// 不同的程序会得到不同的结果吗?有个程序能得到不同的结果,但后来证明他的结果是错的
//该算法有点在于在于找最少的交换次数,不是在于用最少的时间进行排序,此算法的排序时间不是最少的。因为算法的查找时间太长了。
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <Math.h>
#include <assert.h>
using namespace std;
#define N 10//7
class 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减少到715
for(int i=1;i<pCakeNum;i++)
{
if((pCakeArr[i]-pCakeArr[i-1]==1)||(pCakeArr[i]-pCakeArr[i-1]==-1))
;
else
num++;
}
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 ;
}
};
//myPizza
int _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 他的程序确实有问题