120 - Stacks of Flapjacks

题意:
读入一串数字, 通过"翻炒(flip)"使其从小到大有序. "翻炒(flip)" 指的是从某一部分开始, 把从当前到最顶的部分全部反置, "翻炒(flip)"如下如示(最底下坐标是1, 往上递增):
         8                7               2
         4                6               5
         6  flip(3)  4  flip(1) 8
         7                8               4
         5                5               6
         2                2               7

思路:
保证每次flip之后当前操作区间的最大值都在最底部
1. 若已经在最底部, 则不进行操作.
2. 若不在最底部, 则通过两步:
(1). flip 当前最大值, 使其到最顶端;
(2). flip 当前最底部, 使(1)中的最顶端的最大值翻到最底部.
3. 反复直至所有的数字都从小到大有序即可.

要点:
1. 使用 istringstream 从 string 读入. // <sstream>
2. 使用 copy(pancakes.begin(), pancakes.end(), ostream_iterator<int>(cout, " ")); 输出.

题目:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=98&page=show_problem&problem=56

代码:

# include <iostream>
# include <string>
# include <cstdio>
# include <cstring>
# include <vector>
# include <algorithm>
# include <cctype>
# include <iterator>
# include <assert.h>
# include <sstream>   // istringstream
using namespace std;

// istringstream 从 string 读入 int
// 使用 copy 进行输出

typedef vector<int>::iterator IIT;

// 判断 vt 是否从小到大有序
bool isOrder(const vector<int>& vt) {
  if (vt.size() <= 1)
    return true;

  for (int i=1; i<vt.size(); i++) {
    if (vt[i-1] > vt[i])
      return false;
  }

  return true;
}

// 获取 vt 中, 从 0 到 end 的最大值的下标
int getMaxIndex(vector<int>& vt, int end) {
  int max = 0;
  int maxIndex = -1;

  for (int i=0; i<end; i++) {
    if (vt[i] > max) {
      max = vt[i];
      maxIndex = i;
    }
  }

  assert(maxIndex != -1);
  return maxIndex;
}

// 翻转 [begin, end) 之间的数据
void reverse(vector<int>& pancakes, int begin, int end) {
  --end;

  while (begin < end) {
    swap(pancakes[begin], pancakes[end]);
    ++begin;
    --end;
  }
}

// 翻炒区间 [0, end), 保证最大的值在最后即可
void flip(vector<int>& pancakes, int end, vector<int>& flips) {
  int maxIndex = getMaxIndex(pancakes, end);

  // 若不在最下面, 就翻炒两次, 先翻到最上面, 再把 max 翻到最下面
  if (maxIndex != (end-1)) {
    // 若在最上面, 就不用再翻到上面
    if (maxIndex != 0) {
      flips.push_back(pancakes.size() - maxIndex);
      reverse(pancakes, 0, maxIndex+1); 
    }

    flips.push_back(pancakes.size() - end + 1);
    reverse(pancakes, 0, end);
  }
}

// 翻炒 pancake, 使其满足从大到小排列
vector<int> flip(vector<int> pancakes) {
  vector<int> flips;
  
  int numOrdered = 0;
  while (!isOrder(pancakes)) {
    flip(pancakes, pancakes.size() - numOrdered, flips);
    ++numOrdered;
  }

  flips.push_back(0);
  return flips;
}


int main(int argc, char const *argv[])
{
  #ifndef ONLINE_JUDGE
    freopen("120_i.txt", "r", stdin);  
    freopen("120_o.txt", "w", stdout); 
  #endif
  
  // 算法: 每次把要把最大的翻炒到最下面
  // 若这个最大的在中间, 则先从它开始, 把它翻炒到最上面, 再 1, 炒到最下面
  string line;
  while (!cin.eof()) {
    getline(cin, line);

    vector<int> pancakes;
    istringstream iss(line);

    int pancake;
    while (!iss.eof()) {
      iss >> pancake;
      pancakes.push_back(pancake);
    }

    copy(pancakes.begin(), pancakes.end(), ostream_iterator<int>(cout, " ")); 
    cout << endl; 

    vector<int> flips = flip(pancakes);
    copy(flips.begin(), flips.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
  }

  return 0;
}


环境: C++ 4.5.3 - GNU C++ Compiler with options: -lm -lcrypt -O2 -pipe -DONLINE_JUDGE

转载于:https://my.oschina.net/zenglingfan/blog/146745

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值