11111 - Generalized Matrioshkas

题意:
嵌套玩具, 要求外层玩具的尺寸比内层玩具尺寸的和要大. 每一个玩具由一个负数与相应的正数表示, 在这两数之间的部分即为此玩具内部的玩具. 要求判断一串输出的数字是否能组成一个合法的玩具. 一个合法的玩具:
1. 数字代表了 toy 的尺寸大小.
2. 外层的 size 必须 > 内层 size 的和, 不能是 >=.
3. 每次必须是负正对一起出现.

思路:
1. 使用 vector 存放所有输入的数字, list 从尾至头表示已处理过的玩具.
2. 每次从头到尾遍历 vector, 碰到负数, 就依次添加到 list 的首部.
3. 当 vector 碰到一个正数时, 就从 list 的首部向尾查找, 找到第一个负数, 若能找到, 且这个负数与正数是匹配的, 则这是一个玩具.
4. 计算 list 首至负数之间的正数和是否小于当前正数, 若小于, 说明此玩具是合法的, 接着把 list 首至负数之间的所有正数都删掉, 替换成刚才碰到的正数.
5. 即当一个玩具匹配完后, 就只是保存其最外层的数据, 而不再考虑其内部包含的其他玩具.
6. 最后 list 中存放的应该是所有已处理好的玩具.

要点:
1. 用 istringstream 从 string 中读取整数.

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

代码:

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

typedef list<int>::const_iterator LCIT;
typedef list<int>::iterator LIT;

// 添加一个新的 matrioshka, 即把从 [begin, end) 之间的数都去掉, 然后新增一个 k
void addNewMatrioshka(list<int>& matrioshka, LIT end, int k) {
  matrioshka.erase(matrioshka.begin(), end);
  matrioshka.push_front(k);
}

// 返回链表中从头至尾第一个负数
LIT getFirstNegative(list<int>& matrioshka) {
  LIT it;
  for (it = matrioshka.begin(); it != matrioshka.end(); it++) {
    if (*it < 0) break;
  }
  return it;
}

// 判断新得到的 matrioshka 是否是有效的, 即要使当前数与 k 互为正负
// 且要使 [begin, end]) 之间的正数和小于 k
bool isMatrioshkaValid(const list<int>& matrioshka, LCIT end, int k) {
  if (*end != (-1*k)) return false;

  int size = 0;
  for (LCIT it = matrioshka.begin(); it != end; it++) {
    assert (*it > 0);
    size += *it;
  }
  return (size < k);
}

// 判断是否为一个合法的玩具
bool isMatrioshka(const vector<int>& sizes) {
  list<int> matrioshka; 
  for (int i=0; i<sizes.size(); i++) {
    if (sizes[i] < 0) {
      matrioshka.push_front(sizes[i]);
    } else {
      LIT it = getFirstNegative(matrioshka);
      if (it != matrioshka.end() && 
          isMatrioshkaValid(matrioshka, it, sizes[i])) {
          addNewMatrioshka(matrioshka, ++it, sizes[i]);
      } else {
        return false;
      }
    }
  }

  // 最后应该都是正数, 因为一行中可能会包含多个 toys
  if (!matrioshka.empty()) {
    for (LCIT it = matrioshka.begin(); it != matrioshka.end(); it++) {
      if (*it < 0) return false;
    }
    return true;
  }

  return false;
}


int main(int argc, char const *argv[])
{
  #ifndef ONLINE_JUDGE
    freopen("11111_i.txt", "r", stdin);  
    freopen("uva_o.txt", "w", stdout); 
  #endif
  
  string line;
  while (getline(cin, line)) {
    istringstream iss(line);
    vector<int> sizes;

    int k;
    while (iss >> k) {
      sizes.push_back(k);
    }

    if (isMatrioshka(sizes)) {
      cout << ":-) Matrioshka!" << endl;
    } else {
      cout << ":-( Try again." << endl;
    }
  }

  /* 此题如果按以下形式读取,就总会报 WA,为什么??? 最后的空行会输出文字,而不是答案需要的
     不处理!!!
  string line;
  while (!cin.eof()) {
    getline(cin, line);
    istringstream iss(line);
    vector<int> sizes;

    while (!iss.eof()) {
      int k;
      iss >> k;
      sizes.push_back(k);
    }
    ...
  }
  */
  return 0;
}

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

参考: 这里用栈来解, 解法很不错  http://www.cppblog.com/rakerichard/archive/2011/04/14/144183.html

你可能感兴趣的:(uva,Matrioshkas,11111,Generalized)