其他分享
首页 > 其他分享> > 紫书第八章例题笔记

紫书第八章例题笔记

作者:互联网

煎饼(Stacks of Flapjacks, UVa120)

题目链接

有一叠煎饼正在锅里。煎饼共有\(n(n≤30)\)张,每张都有一个数字,代表它的直径大小,如图8-11所示。flip(k)操作可以把铲子插到倒数第k张煎饼下面,并且翻转铲子上面所有的煎饼。例如,图8-11(a),依次执行操作flip(3),flip(1)后得到图8-11(c)的情况。

设计一种方法使得所有煎饼按照从小到大排序(最上面的煎饼最小)。输入时,各个煎饼按照从上到下的顺序给出。例如,上面的例子输入为8, 4, 6, 7, 5, 2

输入输出

输入包含多行,每行是一组以空格分开的数字,这些是煎饼的直径。直径不会超过100,每组数不会超过30。输入代表初始时这些煎饼的序列。

对于每组输入,输出原序列和flip操作的参数,每组输出以0结束。

Sample Input
1 2 3 4 5
5 4 3 2 1
5 1 2 3 4

Sample Output
1 2 3 4 5
0
5 4 3 2 1
1 0
5 1 2 3 4
1 2 0

思路

看到题目都傻了,没啥规律可循,题目中没说明要求输出的内容中flip次数最少还是咋样,就给你几个输入输出让你做。

紫书中的思路是,假设有n个煎饼,每次在[1~n]范围找直径最大的煎饼,如果它在位置k,先用flip(k)把它放到顶上,再用flip(1)让它到底部。这时这个直径最大的煎饼已经归到正确的位置了,我们缩小范围至[1~n-1],重复上面步骤。

这样确实能得到正确结果,思路也很巧妙,但是我还是不知道也不给一个输出的详细要求就让我做怎么做啊,会不会存在其他flip参数序列也能将煎饼排序???

代码

刚开始没想太多直接开始编码了,导致写的乱七八糟,心里在想很多时间优化策略,但是就这问题的输入规模,\(O(n^3)\)的时间复杂度也无所谓吧。所以应该追求简洁易懂。

#include "iostream"
#include "cstdio"
#include "string"
#include "sstream"
#include <algorithm>
#include "cmath"
#include "cstring"

using namespace std;

string line;
int stack[31]; // stack[i] 当前栈中第i张饼的直径 从1开始
int position[101]; // position[n] 饼面直径为n的元素所在栈中的位置,因为并无相同直径的饼 从1开始
int n,maxi = 0;

void read() {
    memset(position, -1, sizeof(position));
    stringstream ss(line);
    n = 1;
    while (ss >> stack[n]) { position[stack[n]] = n;maxi = max(stack[n++],maxi); }
    n--;
    for (int i = 1; i <= n; i++) 
        printf("%d%c", stack[i], i == n ? '\n': ' ');
}

void swap(int* p, int* q) {
    int t = *p; *p = *q; *q = t;
}

// 从倒数第pos个开始,将i到上面的所有翻转
void flip(int pos){
    if (pos == n)return;
    cout << pos << " ";
    for (int i = n - pos + 1, j = 1; i > j; i--, j++) {
        position[stack[i]] = j; position[stack[j]] = i;
        swap(stack + i, stack + j);
    }
}
void solve(){
    int correctCnt = 0; // 已经在正确位置的饼的数量
    for (int i = maxi; i >= 0 && correctCnt <= n; i--) {
        if (position[i] != -1) {
            // 位置不正确,翻转
            if(position[i] != n-correctCnt){
                flip(n-position[i]+1); flip(correctCnt+1);
            }
			correctCnt++;
        }
    }
}

int main() {
    while (getline(cin,line)) {
        read();
        solve();
        printf("0\n");
    }
    return 0;
}

标签:include,紫书,int,flip,第八章,煎饼,position,例题,stack
来源: https://www.cnblogs.com/lilpig/p/14276603.html