烙饼排序

来源:互联网 发布:awardrotate.js官网 编辑:程序博客网 时间:2024/04/27 18:51

 

星期五的晚上,一帮同事在希格玛大厦附近的“硬盘酒吧”多喝了几杯。程序员多喝了几杯之后谈什么呢?自然是算法问题。有个同事说:“我以前在餐馆打工,顾客经常点非常多的烙饼。店里的饼大小不一,我习惯在到达顾客饭桌前,把一摞饼按照大小次序摆好——小的在上面,大的在下面。由于我一只手托着盘子,只好用另一只手,一次抓最上面的几块饼,把它们上下颠倒个个儿,反复几次之后,这摞烙饼就排好序了。我后来想,这实际上是个有趣的排序问题:假设有n块大小不一的饼,那最少要翻几次,才能达到最后大小有序的结果呢?你能否写出一个程序,对于n块大小不一的烙饼,输出最优化的翻饼过程呢?

 

 

 

 

 

这是一个求最优化的问题,此题不能用动态规划编写。因为其没有最优子结构,所以只有遍历完所有的情况,挑选其中最优的。但是在搜索的过程中可以添加减支函数,减少搜索的次数。关键是递归函数的编写。

for(int i=1;i<len;++i)
 {
      if(count!=0&&temp[count]==i)
      continue;
      reverse(data,i);
      temp[count+1]=i;
      pee(data,len,count+1);
      reverse(data,i);//回到上一个状态
 }//递归的翻转过程,搜索树的遍历

还有就是减支函数的设计,根据当前的数组的值,可以求出到最后的状态至少需要翻转的次数,所以可以通过这个设计减支函数,减支函数的设计的优劣直接影响到搜索的效率。

 

代码如下:

 

#include<iostream>using namespace std;int min;//记录所需要翻转的最少的次数int *temp,*result;//temp数组保存中间的翻转步骤的结果,result保存翻转的步骤int Lowbound(int *parray,int cakenum){int t=0,ret=0;for(int i=0;i<cakenum-1;i++){t=parray[i]-parray[i+1];if((t==1)||(t==-1)){}elseret++;}return ret;}//烙饼在当前状态的最少需要的翻转次数void reverse(int *data,int index){//翻转函数 将0---index翻转int i=0,j=index;int temp;while(i<j){temp=data[i];data[i]=data[j];data[j]=temp;++i;--j;}}//翻转操作bool over(int *data,int len){for(int i=1;i<len;++i)if(data[i-1]>data[i])return false;if(i==len)return true;return false;}//判断翻转的结果是否达到要求int cnt=0;//记录翻转的总次数void pee(int *data,int len,int count=0){cnt++;int Estimate=Lowbound(data,len);if((count+Estimate)>min)return;//减支函数if(over(data,len)){if(min>count){min=count;memcpy(result,temp,sizeof(int)*(2*(len)));cout<<"当前最少搜索次数cur_min="<<min<<endl;for(int i=1;i<=min;i++){cout<<result[i]+1<<" ";}cout<<endl;}return;}for(int i=1;i<len;++i){if(count!=0&&temp[count]==i)continue;//若搜索完一步之后,立刻回到了上一个状态,则不需要继续搜索,直接去掉这一支,也算是一个减支函数reverse(data,i);temp[count+1]=i;pee(data,len,count+1);reverse(data,i);}//递归求翻转过程,其实是一棵搜索树}void main(){int Cake_num;//烙饼的个数cout<<"请输入烙饼的个数:"<<endl;cin>>Cake_num;cout<<"请依次输入烙饼的大小:"<<endl;int *Cake_array=new int[Cake_num];//存放烙饼的数组temp=new int[2*(Cake_num)];result=new int[2*(Cake_num)];for(int i=0;i<Cake_num;i++){cin>>Cake_array[i];}for(i=0;i<2*(Cake_num-1);i++){temp[i]=0;result[i]=0;}min=2*(Cake_num);pee(Cake_array,Cake_num);cout<<"-------------------"<<endl;cout<<"最少的翻转次数max="<<min<<endl;cout<<"翻转的过程:"<<endl;for(i=1;i<=min;i++){cout<<result[i]+1<<" ";}cout<<endl;cout<<"Total Run Times: "<<cnt<<endl;}