Uva 120 Stacks of Flapjacks 解题报告

来源:互联网 发布:南昌百盛有mac魅可专柜 编辑:程序博客网 时间:2024/06/09 23:36

Stacks of Flapjacks(煎饼)

Background

Stacks and Queues are often considered the bread and butter of data structures and find use in architecture, parsing, operating systems, and discrete event simulation. Stacks are also important in the theory of formal languages.

栈和队列经常被认为是数据结构中的面包和黄油,并且广泛应用在体系结构、分析、操作系统和离散化等领域。栈同时也在形式语言理论中发挥着重要的作用。

This problem involves both butter and sustenance in the form of pancakes rather than bread in addition to a finicky server who flips pancakes according to a unique, but complete set of rules.

这个问题是一个挑剔的厨师用一种独特的方式翻动煎饼,使得煎饼(而不是面包)中的黄油和营养不被破坏。(对于我这种英语缺

陷的人来说,翻译这种令人无语的句子真是一种折磨啊...)

The Problem

Given a stack of pancakes, you are to write a program that indicates how the stack can be sorted so that the largest pancake is on the bottom and the smallest pancake is on the top. The size of a pancake is given by the pancake's diameter. All pancakes in a stack have different diameters.

给出一叠煎饼,你需要把它们从小到大进行排序,使得最大的在底部,最小的在顶部。给出煎饼的直径作为它的尺寸。每一个煎饼的的直径都是不同的。

Sorting a stack is done by a sequence of pancake ``flips''. A flip consists of inserting a spatula between two pancakes in a stack and flipping (reversing) the pancakes on the spatula (reversing the sub-stack). A flip is specified by giving the position of the pancake on the bottom of the sub-stack to be flipped (relative to the whole stack). The pancake on the bottom of the whole stack has position 1 and the pancake on the top of a stack of n pancakes has position n.

煎饼的排序是通过一种“翻转”实现的。一次翻转(...这一部分好难翻译啊...)是把铲子放在两个煎饼之间,然后把上面的煎饼倒转过来。每个翻转是由开始位置决定的,即铲子上面的最下面的那张煎饼(是铲子放进的两个煎饼中上面的那个)的编号。最下面的那张编号是1,最上面的那张编号是n。

A stack is specified by giving the diameter of each pancake in the stack in the order in which the pancakes appear.

煎饼由一组表示其中各煎饼直径的数构成,它们排列的顺序就是给出的这些数的顺序。

For example, consider the three stacks of pancakes below (in which pancake 8 is the top-most pancake of the left stack):

比如下面的三煎饼(煎饼8是左边一叠的最上面的一个):

         8           7           2         4           6           5         6           4           8         7           8           4         5           5           6         2           2           7
The stack on the left can be transformed to the stack in the middle via flip(3). The middle stack can be transformed into the right stack via the command flip(1).

左边一叠可以通过从第3个煎饼开始翻转变成中间一叠的顺序。中间一叠可以通过从第1个煎饼开始翻转变成右边一叠的顺序。

The Input

The input consists of a sequence of stacks of pancakes. Each stack will consist of between 1 and 30 pancakes and each pancake will have an integer diameter between 1 and 100. The input is terminated by end-of-file. Each stack is given as a single line of input with the top pancake on a stack appearing first on a line, the bottom pancake appearing last, and all pancakes separated by a space.

输入包括许多叠煎饼。每叠都由1到30个煎饼组成,并且每个煎饼的直径都在 1到100之间。输入由EOF结束。每叠煎饼独占一行,最上面的在行首,最下面的在行尾,各煎饼中间由空格隔开。

The Output

For each stack of pancakes, the output should echo the original stack on one line, followed by some sequence of flips that results in the stack of pancakes being sorted so that the largest diameter pancake is on the bottom and the smallest on top. For each stack the sequence of flips should be terminated by a 0 (indicating no more flips necessary). Once a stack is sorted, no more flips should be made.

对应于每叠煎饼数据,必须在第一行输出原来这叠煎饼的内容,接下来输出一组翻转动作的序列,使得这一叠煎饼自底向上由大至小的排列。输出的每一组翻转动作序列都要由0来结束(表示不再进行翻转)。一旦一叠煎饼已经排好序,就不能再进行任何翻转。

Sample Input

1 2 3 4 55 4 3 2 15 1 2 3 4

Sample Output

1 2 3 4 505 4 3 2 11 05 1 2 3 41 2 0
终于翻译完题了,接下来可以分析一下题意,本题是要让我们通过不断地“翻转”,即将一段序列颠倒,来实现从小到大的排序。
第一眼看上去好像有些没有思路,不过仔细想想不难发现,由于翻转是在从一个点向上到顶端这段区间内进行的,所以可以从下往上逐渐把每个煎饼归位(因为上面的对下面的没有影响),这样的话就变成了先把煎饼的大小从大到小排序,然后从大到小把每个煎饼先翻到最上面(这样接下来就只需要一次把它翻到应该处在的位置上了)。
Code:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int a[101],b[101],c[100001];int z[301]; bool cmp(int x,int y){return x>y;}int find(int x,int n){for (int i=1; i<=n; i++)if (a[i]==x){return i;break;}}int main(){int n,i=0,j=0,k=1,l=0,x,p=0;char ch;memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));memset(z,-1,sizeof(z));while (scanf("%c",&ch)==1){if (ch!='\n') z[++i]=ch-'0';else if (ch=='\n'){n=i;int v=0;for (i=1; i<=n; i++){if (z[i]>0 && z[i+1]<0){a[++v]=z[i];z[i]=-1;}else if (z[i]>0 && z[i+1]>=0 && z[i+2]<0){a[++v]=z[i]*10+z[i+1];z[i]=-1;z[i+1]=-1;}else if (z[i]>0 && z[i+1]>=0 && z[i+2]>=0){a[++v]=z[i]*100+z[i+1]*10+z[i+2];z[i]=-1;z[i+1]=-1;z[i+2]=-1;}else if (z[i]>0 && z[i+1]==0){a[++v]=z[i];z[i]=-1;}}while (a[n]==0) n--;for (i=1; i<=n; i++){printf("%d ",a[i]);b[i]=a[i];}printf("\n");sort(b+1,b+n+1,cmp);for (i=n; i>=1; i--){if (a[i]==b[n-i+1]) continue;k=find(b[n-i+1],n);if (k!=1){l++;c[l]=n-k+1;for (j=1; j<=k/2; j++){a[j]^=a[k-j+1];a[k-j+1]^=a[j];a[j]^=a[k-j+1];}} if (a[1] != b[n]){l++;c[l]=n-i+1;for (j=1; j<=i/2; j++){a[j]^=a[i-j+1];a[i-j+1]^=a[j];a[j]^=a[i-j+1];}}}for (i=1; i<=l+1; i++) printf("%d ",c[i]);printf("\n");i=0;l=0;memset(a,0,sizeof(a));memset(c,0,sizeof(c));memset(z,-1,sizeof(z));}}return 0;}
中间做了许多很笨的转换方法...比如字符转数字用流的话会简单许多...还有就是把交换两个变量写成了异或的形式...貌似有些多余,欢迎轻喷...
0 0