zoukankan      html  css  js  c++  java
  • UVa120 煎饼(选择排序思想)

    题目背景

    给你一迭薄煎饼,请你写一个程式来指出要如何安排才能使这些薄煎饼由上到下依薄煎饼的半径由小到大排好。所有的薄煎饼半径均不相同。

    要把薄煎饼排好序需要对这些薄煎饼做翻面(flip)的动作。方法是以一抹刀插入一迭薄煎饼中,然后做翻面的动作(也就是说在抹刀上面的薄煎饼经翻面后,会依相反的次序排列)。若一迭共有(n)个薄煎饼,我们定义最底下的薄煎饼的位置为1,最上面的薄煎饼位置为(n)。当抹刀插入位置为(k)时,代表从位置(k)到位置(n)的薄煎饼要做翻面的动作。

    一开始时,这迭薄煎饼随意堆放,并以半径大小来表示。例如:以下3迭薄煎饼(最左边那一迭8是最上面一个薄煎饼的半径)

     8           7           2
     4           6           5
     6           4           8
     7           8           4
     5           5           6
     2           2           7
    

    对最左边那迭薄煎饼,如果我们把抹刀插在位置3(就是半径为7的那块薄煎饼的下面)的地方做翻面,就会得到中间那迭,如果我们再把抹刀插在位置1(就是半径为2的那块薄煎饼的下面)的地方做翻面,就会得到最右边那迭。

    Input

    每组测试资料一行,内容为这一迭薄煎饼一开始的状态。每列开始的整数(介于1到100之间)代表位于最上方薄煎饼的半径,依此类推。薄煎饼的数目介于1到30之间。请参考输入样例。

    Output

    对每一组测试资料输出2列。第一列为原来那迭薄煎饼。第2列则为要使这迭薄煎饼由小到大排列所做的翻面的动作。数字代表抹刀所插入的位置。(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
    

    题解

    如果我们设题目输入数组为(A),长度为(n)。那么我们需要注意的一点是,(A[0])对应一叠煎饼的顶端,(A[n-1])对应一叠煎饼的底部。如下图所示:
    uVa120 煎饼
    故要想将数组倒数第(i)个位置及其之前的元素(即(A[0:n-i]))翻转,我们输出的抹刀插入位置为(i)
    采用选择排序的思想,按从大到小的顺序依次把元素移动到正确位置,一共(n)轮,其中第(i)轮((i=1,2,...,n))排序把数组(A[0:n-i])中最大的元素移动到下标(n-i)处(如果本身就在下标(n-i)处则跳过)。
    不过这里我们只能翻转一个序列,故我们需要用到一个技巧,就是分两步走:
    ① 先将(A[0:n-i])中最大的元素“翻”到最左端的下标(0)处(如果本身就在下标(0)处则跳过)。
    ② 然后再将它“翻”到正确位置即下标(n-i)处。
    设数组(A[0:n-i])中数组最大元素的下标为(maxs),前者需要将(A[0:maxs])(即倒数第(n - maxs)个位置及其之前的元素)翻转,此时输出的抹刀插入位置应为(n-maxs);后者需要将(A[0:n-i])(即倒数第(i)个位置及其之前的元素翻转,此时输出的抹刀插入位置应为(i)
    根据以上的分析,我们的算法如下:

    '''
    Descripttion: 选择排序思想
    Version: 1.0
    Author: ZhangHongYu
    Date: 2021-08-12 15:54:27
    LastEditors: ZhangHongYu
    LastEditTime: 2021-08-28 22:01:07
    '''
    while True:
        try:
            A = list(map(int, input().strip().split()))
            t = A.copy()
            res = []
            n = len(A)
            # 排序趟数
            for i in range(1, n+1):
    
                # 获取A[0:n-i]中最大元素的下标
                max_v = max(A[: n - i + 1])
                maxs = A[: n - i + 1].index(max_v)
    
                # 如果最大元素还未翻到下标n-i处
                if maxs != n - i:
                    # 如果最大元素还未翻到下标0处
                    if maxs != 0:
    
                        # 将A[0:maxs]翻转
                        A[: maxs + 1] = list(reversed(A[: maxs + 1]))
                        # 此时抹刀插入位置应为 n - maxs
                        res.append(n - maxs)  # 
                    
                    # 将A[0:n-i]翻转
                    A[: n - i + 1] = list(reversed(A[: n - i + 1]))
                    # 此时抹刀插入位置应为i
                    res.append(i)
    
            res.append(0)
            print(" ".join(map(str, t)))
            print(" ".join(map(str, res)))
        except EOFError:
            break
    
    数学是符号的艺术,音乐是上界的语言。
  • 相关阅读:
    转载2010年3月4日dojo学习笔记 dojo.disconnect
    转载谈谈JS里的{ }大括号和[ ]中括号的用法,理解后就可以看懂JSON结构了
    设置鹰眼(ArcGIS API for JavaScript)
    不安装Oracle10g客户端连接Oracle10g数据库【转】
    发布“个人知识库管理”软件,欢迎下载使用
    [转]更好地使用Google的服务
    技术资源:国内知名技术网站网址
    UrlRewritingNet与FCKEditor同时使用时需要注意的问题
    webreqeust/webresponse抓取URL信息
    javascript更改iframe链接的注意事项
  • 原文地址:https://www.cnblogs.com/lonelyprince7/p/15201934.html
Copyright © 2011-2022 走看看