题目大意:煎饼排序。
这个问题是Bill Gates想出来的。描述如下。
一位餐厅侍者在送出一叠煎饼 (pancakes) 到顾客之前,发现厨师实在太困了,这些煎饼大小不一,混杂在一起堆成一叠,客人实在不会有太多好感。因此,在送出这些煎饼之前,这位侍者会使用一片锅铲将这些煎饼重新排成一叠由小而大排列的煎饼。不过,由于盘子太小,我们不能够将煎饼平铺后再重新排一次,而只能用锅铲卡在某个煎饼的下方,将上头全部的煎饼一起做翻面的动作。比如说,这裡有三块煎饼,最大的一块叫做3,中间大小的是2,最小的一块就是1。如果1号在盘子的最下面,3号煎饼叠在它上面,最上面的煎饼就是2号;由上而下的排列就是:(2,3,1)。那么,侍者就可以先用锅铲卡在第二个煎饼的下方,将前2个煎饼做翻面的动作,这三个煎饼顺序就成了:(3,2,1);然后,侍者就可以再用锅铲卡在第3个煎饼的下方,将全部煎饼做翻面的动作,这三个煎饼顺序就成了:(1,2,3)。好了,我们这位高兴的侍者就可以赶紧将这些排好的煎饼送出去给客人了。
具体问题描述:http://semoncat.github.io/blog/2012/11/05/pancake-sorking/
解题思路:
1.当然可以进行裸深搜,但是想不出剪枝的方法,可能TLE所以没进行尝试。
2.迭代深搜。在深搜之前预测一个搜索深度最小值,搜索深度不超过这个值。如果找到返回,如果找不到增加搜索深度。
数据结构:index[],num[]
index为num索引,目的将输入数字映射成0,1,2,3,4...n
主要函数:
1.bool comp()。 通过num大小对index进行排序。
如实际输入为6,8,2,4,排序后的index为3,2,1,4。
将index排序为1,2,3,4次数相当于将实际输入排序还原为6,8,2,4。
从6,8,2,4到2,4,6,8和从2,4,6,8到6,8,2,4排序次数相同。
2.inline int dfs_depth()。 得到一个预期搜索深度的最小值。即最小交换次数。
当相邻两数差值绝对值大于1时,至少需要交换一次才可以完成排序。
计算有多少对相邻数差值绝对值大于1,得到初始搜索深度。
3.bool dfs( int depth )。迭代深搜。
// 1142. Pancake Sorting(煎饼排序)
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
// index为num建立索引
int n,index[26],num[26];
inline bool isFinished(); // 判断是否完成排序
inline int dfs_depth(); // 得到至少交换次数,才能完成排序
bool comp( const int& a, const int& b );
bool dfs( int depth );
int main(){
scanf("%d",&n);
for( int i = 0; i < n; ++i ){
index[i] = i;
scanf("%d",num+i);
}
sort( index, index+n, comp );
int cnt = dfs_depth();
// 如果当前深度不满足排序,则增加搜索深度。
while( !dfs( cnt++ ) ){}
printf("%d\n",cnt-1);
return 0;
}
bool comp( const int&a, const int& b ){
return num[a] < num[b];
}
inline bool isFinished(){
for( int i = 0; i < n - 1; ++i ){
if( index[i] > index[i+1] ) return false;
}
return true;
}
inline int dfs_depth(){
int depth = 0;
for( int i = 0; i < n - 1; ++i ){
// 如果相邻的值差值大于1,那么必须进行一次交换
// 差值为1可以在其他交换时,同时进行交换
depth += ( fabs( float(index[i] - index[i+1]) ) > 1 );
}
return depth;
}
bool dfs( int depth ){
// depth为0表示序列不存在差值大于1的相邻数,则判断是否有序
if( depth == 0 ){
if( isFinished() ) return true;
else return false;
}
// 排序次数必须大于最少交换次数
if( depth < dfs_depth() ) return false;
for( int i = 2; i <= n; ++i ){
reverse( index, index+i );
if( dfs(depth-1) ) return true;
reverse( index, index+i ); // 如果当前状态无法得到结果,则返回初始序列
}
return false;
}