题目描述
给你一叠薄煎饼,请你写一个程序来指出要如何安排才能使这些薄煎饼由上到下依薄煎饼的半径由小到大排好。所有的薄煎饼半径均不相同。要把薄煎饼排好序需要对这些薄煎饼做翻面(flip)的动作。方法是以一抹刀插入一叠薄煎饼中,然后做翻面的动作(也就是说在抹刀上面的薄煎饼经翻 面后,会依相反的次序排列)。若一叠共有n个薄煎饼,我们定义最底下的薄煎饼的位置为1,最上面的薄煎饼位置为n。当抹刀插入位置为k时,代表从位置k到 位置n的薄煎饼要做翻面的动作。一开始时,这叠薄煎饼随意堆放,并以半径大小来表示。最后输出一系列位置代表刀插入的位置。以0结尾;
分析
题意给的数据量不大,而且输出的一组可行解,所以我们可以逐个解决,如:先将最大的饼先放到最下面,那么接下来所有的操作都不会涉及到最大的饼,从而问题的规模减小了。以此类推每次都将当前问题中的最大的放到最下面,最终可以得到可行解。
代码分析
//将数组下标范围为[0,p]之间的数组反转
void flip(int p)
{
for (int i = 0; i < p-i; i++)
swap(dat[i], dat[p - i]);
printf("%d ", n - p);
}
这个函数可以借鉴其中的方法,用到需要将数组部分区间的元素反转。其中最靓的部分是for (int i = 0; i < p-i; i++)其中的循环结束条件是i小于p-i,可以避免求区间中间的值而废脑筋。
其他的一些细节代码中有注释。其中用到了一个函数:max_element();该函数介绍如下
//The behavior of this function template is equivalent to:
//**Return largest element in range**
template <class ForwardIterator>
ForwardIterator max_element ( ForwardIterator first, ForwardIterator last )
{
if (first==last) return last;
ForwardIterator largest = first;
while (++first!=last)
if (*largest<*first) // or: if (comp(*largest,*first)) for version (2)
largest=first;
return largest;
}
返回数组中最大的元素的下表,返回的下标从0开始;
/*
problem:Stacks of Flapjacks UVA - 120
author:zxz
time:0ms
memory:
disadvantage:
*/
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <math.h>
#include <queue>
#include <string>
#include <sstream>
#include <vector>
#include <string.h>
#include <time.h>
using namespace std;
const int maxn = 111;
const int INF = 111;
int dat[33];int n = 0;
void init()
{
n = 0;
}
void flip(int p)
{
for (int i = 0; i < p-i; i++)
swap(dat[i], dat[p - i]);
printf("%d ", n - p);//反转结束后输出n-p,是因为数据是前面的元素代表顶端的饼
}
void solve()
{
string s;
while (getline(cin, s))
{
stringstream ss(s);
init();
while (ss >> dat[n]) n++;
cout << s << endl;
for (int i = n-1; i > 0; i--)//只处理前n-1个,剩下的最后一个已经在正确的位置上了
{
int p = max_element(dat, dat + i + 1) - dat;
if (p == i) continue;//如果一样说明饼已经在正确的位置了
if (p > 0) flip(p);//如果当前最大的饼在0这个位置说明饼已经在顶端了
//不需要再执行反转到顶端的操作
flip(i);
}
printf("0\n");
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("cin.txt", "r", stdin);
//freopen("cout.txt", "w", stdout);
int mao = clock();
#endif
solve();
#ifndef ONLINE_JUDGE
cerr << "Time:" << clock() - mao << "ms" << endl;
#endif
return 0;
}