SWUST OJ 254:翻煎饼问题
问题描述:
麦兜最喜欢的食物是煎饼,每次在街上看到煎饼摊的时候都会在那里停留几分钟。最吸引麦兜还是煎饼师傅那一手熟练的翻煎饼的技术,一堆煎饼在那里,师傅只需要用铲子翻几下,就让煎饼整齐的叠在了一起。 这天,为了庆祝麦兜被保送上研究生,他从煎饼师傅那里买回来一些煎饼请客。但是麦兜买回的煎饼大小不一,麦兜太想吃煎饼了,他想吃这些煎饼中最大的那个。麦兜还知道同学们也很喜欢煎饼,为了表示他的诚意,他想让同学们先吃,麦兜最后吃,因此,麦兜想把煎饼按照从小到大的顺序叠放在一起,大的在最下面。这样麦兜就可以在最后拿到最大的那一块煎饼了。 现在请你帮助麦兜用煎饼师傅翻煎饼的方法把麦兜买的煎饼从小到大的叠在一起。煎饼师傅的方法是用铲子插入两块煎饼之间,然后将铲子上的煎饼翻一转,这样铲子上第一个煎饼就被翻到了顶上,而原来顶上的煎饼则被翻到了刚才插入铲子的地方。麦兜希望这样翻煎饼的次数最少。
输入:输入包括两行,第一行是一个整数n(1<=n<=1000),表示煎饼的个数,接下来的一行有n个不相同的整数,整数间用空格隔开,每个整数表示煎饼的大小(直径),左边表示顶部,右边表示底部。
输出:输出为一行,翻煎饼的最少次数(注意要换行 \n)
样例:
思路:首先要摸清楚怎么去翻煎饼,其实就是将这n个煎饼的个数,简化成两个煎饼或整体(插入说位置可以是煎饼,也可以是缝隙),分为两个步骤:
1.将相对最大的煎饼翻在最上面
2.再将它翻下来
忽略已确定的位置,重复以上步骤,可以用迭代也可以用递归
翻煎饼的过程有点像镜像
如:(下划线表示位置已确定)
5 4 2 3 1 //将4 2 3 1看作一个煎饼,5看作一个煎饼,翻,得到如下结果
1 3 2 4 5 //4,5位置已确定,只需翻 1,3,2,将1,3开翻
3 1 2 4 5 //将1,3看做一个煎饼,将2看做一个煎饼,开翻
1 2 3 4 5
代码思路:分三种情况
1.相对最大的煎饼在最上面
2.相对最大的煎饼在中间
3.相对最大的煎饼在最下面(已确定)
代码实现(使用C语言)
#include "stdio.h" int num=0; int turn_num =0; int max_button(int a[]) { int i=0; int max=0; int op=0; for(i=0;i<num;i++) { if(max<=a[i]) { max = a[i]; op = i; } } if(op==num-1) { return 1; } else { return 0; } } int max_op(int a[]) { int i=0; int max=0; int op=0; while(a[i]!=0) { if(max<a[i]) { max = a[i]; op = i; } i++; } return op; } void reverse(int a[],int n) { int b[1000]={0}; int i; for(i=0;i<n;i++) { b[n-i-1] = a[i]; } for(i=0;i<n;i++) { a[i] = b[i]; } } void del(int a[]) { int i; int temp = num; for(i=0;i<temp;i++) { if((max_button(a))==1) { a[num-1] = 0; num--; } } } int trun(int a[]) { int op; while(a[0]!=0) { del(a); if(max_op(a)==0) { reverse(a,num); turn_num++; } else{ op = max_op(a); reverse(a,op+1); turn_num++; } } return turn_num; } int main() { int a[3000]={0}; int i; int answer; scanf("%d",&num); for(i=0;i<num;i++) { scanf("%d",&a[i]); } answer = trun(a); printf("%d\n",answer-1); }