https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=56
题目
栈和队列通常被认为和数据结构的面包、黄油一样,在建筑、解析、操作系统和离散事件模拟等领域有应用。栈也对一些严谨的语言很重要。本问题涉及黄油和食物(这里用薄饼代替面包,因为翻动薄饼有一个独特而又完整系统的规则)。
给定一堆摞在一起的薄饼,你需要写个程序计算这摞薄饼怎么排序才能使得最大的薄饼在最底下,最小的薄饼在最上方。薄饼的大小用其直径定义。所有薄饼的直径互不相同。我们用翻转薄饼这个操作来排序这个栈。flip(i)
操作表示翻转最上面到从下往上数的第i个薄饼,即倒置位置。最底下的薄饼为第1个,最上面的薄饼为第n个。
我们这里用一个薄饼的直径组成的栈描述问题。必须考虑只有3个元素的栈(其中最左边那个栈的最上面的8表示栈顶):
8 7 2
4 6 5
6 4 8
7 8 4
5 5 6
2 2 7
第一个栈执行操作flip(3)
后变成第2个栈,再执行flip(1)
后变成第3个栈。
输入
输入包含多组数据,每组数据一行 n(1≤n≤30) 个整数 di(1≤di≤100) (当然n要你自己算)。 di 表示从上往下数的第i个的直径为多少。
输出
对于每组数据,先输出原栈是怎么样的,然后再输出一行表示flip
操作数的数列,并以0结尾表示数列结束(此时栈已经排序好了)。
样例输入
1 2 3 4 5
5 4 3 2 1
5 1 2 3 4
样例输出
1 2 3 4 5
0
5 4 3 2 1
1 0
5 1 2 3 4
1 2 0
题解
由于题目没有说输出的方案的要求,也就是说我们可以随便输出一种,那么我们就可以规定输出的规则。由于我们翻一次薄饼,最底下的是不受影响的,所以如果最大的饼在从下往上数的第i位置,执行flip(i)
再执行flip(1)
就可以把这个饼调整到最底下,然后只要我们不执行flip(1)
,这个饼就不会被动。所以我们把饼从大到小依次执行flip
函数归位即可。
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;
int d[1024], d2[1024];
int main() {
int sz, n, i, j, bottom;
string s;
while (getline(cin, s)) {
cout<<s<<endl;
stringstream ss;
ss<<s; sz = 0;
for (n = 1; ss>>d[n]; ++n) sz = max(sz, d[n]); --n;
bottom = n;
memcpy(d2, d, sizeof d);
sort(d2 + 1, d2 + n + 1);
for (i = n; i > 1; --i) {
for (j = i; d[j] != d2[i]; --j);
if (i == j) continue;
if (j != 1) {
reverse(d + 1, d + j + 1);
cout<<n - j + 1<<' ';
}
reverse(d + 1, d + i + 1);
cout<<n - i + 1<<' ';
}
cout<<0<<endl;
}
return 0;
}