UVA - 120 Stacks of Flapjacks

这篇博客介绍了如何解决UVA 120题目的薄煎饼排序问题。通过翻转操作将薄煎饼按半径从小到大排列,每次选取最大元素放到最下方,递归缩小问题规模。代码中使用了数组部分区间反转技巧和max_element()函数找到最大元素。
摘要由CSDN通过智能技术生成

题目传送门

题目描述

给你一叠薄煎饼,请你写一个程序来指出要如何安排才能使这些薄煎饼由上到下依薄煎饼的半径由小到大排好。所有的薄煎饼半径均不相同。要把薄煎饼排好序需要对这些薄煎饼做翻面(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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值