UVa 120 - Stacks of Flapjacks
链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=56
题意:
有一叠煎饼正在锅里。煎饼共有n(n≤30)张,每张都有一个数字,代表它的大小。
厨师每次可以选择一个数k,把从锅底开始数第k张及上面的煎饼整体翻转过来(即颠倒一个连续子序列)。
设计一种方法使得所有煎饼按照从小到大排序(最上面的煎饼最小)。输入时,各个煎饼按照从上到下的顺序给出。
分析:
构造法。按照选择排序的思想,以从大到小的顺序依次把每个数排到正确的位置。
方法是先翻到最上面,然后翻到正确的位置。
由于是按照从大到小的顺序处理,当处理第i大的煎饼时,是不会影响到第1, 2, 3,…, i-1大的煎饼的
(它们已经正确地翻到了煎饼堆底部的i-1个位置上)。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <sstream> 4 #include <algorithm> 5 using namespace std; 6 7 inline int seek(int* a, int k){ 8 for(int i = 0; ; i++){ 9 if(a[i] == k) return i; 10 } 11 } 12 13 void solve(int* a, int n){ 14 int b[100+5]; 15 memcpy(b, a, sizeof(b)); 16 sort(b, b + n); 17 for(int last = n - 1; last > 0; last--){ 18 if(a[last] == b[last]) continue; 19 if(a[0] != b[last]){ 20 int p = seek(a, b[last]); 21 printf("%d ", n - p); 22 reverse(a, a + p + 1); 23 } 24 printf("%d ", n - last); 25 reverse(a, a + last + 1); 26 } 27 printf("0\n"); 28 } 29 30 int main(){ 31 char s[999]; 32 while(gets(s)){ 33 printf("%s\n", s); 34 int n = 0, a[100+5]; 35 stringstream ss(s); 36 while(ss >> a[n]) n++; 37 solve(a, n); 38 } 39 return 0; 40 }