总结+经典例题重做

Posted 四口鲸鱼爱吃盐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结+经典例题重做相关的知识,希望对你有一定的参考价值。


欢迎交流学习~~


专栏: 蓝桥杯Python组刷题日寄

4 个月前开始写蓝桥杯系列,到目前为止一共是 19 篇,其中:入门篇 5 篇,简单篇 8 篇,进阶篇 6 篇


这篇文章主要是为了为先前内容进行总结,并对其中的部分经典例题进行回顾。


蓝桥杯入门系列:

😜【蓝桥杯入门篇】Python组刷题日寄Part01
😗【蓝桥杯入门篇】Python组刷题日寄Part02
😮【蓝桥杯入门篇】Python组刷题日寄Part03
😍【蓝桥杯入门篇】Python组刷题日寄Part04
😃【蓝桥杯入门篇】Python组刷题日寄Part05

蓝桥杯简单系列:

💙【蓝桥杯简单篇】Python组刷题日寄Part01
💜【蓝桥杯简单篇】Python组刷题日寄Part02
💚【蓝桥杯简单篇】Python组刷题日寄Part03
💗【蓝桥杯简单篇】Python组刷题日寄Part04
💕【蓝桥杯简单篇】Python组刷题日寄Part05
💘【蓝桥杯简单篇】Python组刷题日寄Part06
💖【蓝桥杯简单篇】Python组刷题日寄Part07
💔【蓝桥杯简单篇】Python组刷题日寄Part08

蓝桥杯进阶系列:

🏆 Python | 蓝桥杯进阶第一卷——字符串
🔎 Python | 蓝桥杯进阶第二卷——贪心
💝 Python | 蓝桥杯进阶第三卷——动态规划
✈️ Python | 蓝桥杯进阶第四卷——图论
🌞 Python | 蓝桥杯进阶第五卷——数论
💎 Python | 蓝桥杯进阶第六卷——搜索


Python | 蓝桥杯系列文章总结+经典例题重做

接下来我们从上面的文章中选取一定量的题目,进行回顾总结,并在原先基础上进行改进。


☔ 蚂蚁感冒

来源:💙【蓝桥杯简单篇】Python组刷题日寄Part01

题目:
时间限制:
1s

内存限制:
128MB

题目描述:
100 厘米的细长直杆子上有 n 只蚂蚁。它们的头有的朝左,有的朝右。
每只蚂蚁都只能沿着杆子向前爬,速度是 1 厘米/秒。
当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。
这些蚂蚁中,有 1 只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

输入描述:
第一行输入一个整数 n(1 < n < 50), 表示蚂蚁的总数。
接着的一行是n个用空格分开的整数 Xi(-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现 0 值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。

输出描述:
要求输出 1 个整数,表示最后感冒蚂蚁的数目。

样例输入:

5
-10 8 -20 12 25

样例输出:
3


解题思路

首先我们要计算两个值:leftright
left 表示第一只感冒蚂蚁的左侧, 头向右蚂蚁的数量
right 表示第一只感冒蚂蚁的右侧, 头向左蚂蚁的数量

其次,我们经过分析得到,感冒要传染,只能通过相遇,而不能通过追击

对于第一只感冒的蚂蚁,我们分为两种情况讨论:

  • 头向左
    • 若其左侧头向右的蚂蚁,则左侧的 left 只蚂蚁会依次逐个传染;而第一只感冒蚂蚁会转头,会使右侧的 right 只蚂蚁依次逐个传染;
    • 若其左侧没有头向右的蚂蚁,则不会有蚂蚁传染。
  • 头向右
    • 若其右侧头向左的蚂蚁,则右侧的 right 只蚂蚁会依次逐个传染;而第一只感冒蚂蚁会转头,会使左侧的 left 只蚂蚁依次逐个传染;
    • 若其右侧没有头向左的蚂蚁,则不会有蚂蚁传染。

参考代码

n = int(input())
dis = list(map(int, input().split()))

# k 为第一只感冒蚂蚁距离左边的距离
k = abs(dis[0])

# left 表示第一只感冒蚂蚁的左侧, 头向右蚂蚁的数量
# right 表示第一只感冒蚂蚁的右侧, 头向左蚂蚁的数量
left = right = 0

# 计算最终感冒蚂蚁
for i in dis[1:]:
    # 对于第一只感冒蚂蚁的左侧, 如果头向右
    if 0 < i < k:
        left += 1
    # 对于第一只感冒蚂蚁的右侧, 如果头向左
    if i < 0 and abs(i) > k:
        right += 1

# 如果第一只感冒的蚂蚁头向左, 且 left 不为 0
# 或 第一只感冒的蚂蚁头向右, 且 right 不为 0
if (dis[0] < 0 and left != 0) or (dis[0] > 0 and right != 0):
    print(left + right + 1)
else:
    print(1)


❄️ Sine之舞

来源:💚【蓝桥杯简单篇】Python组刷题日寄Part03

题目:
时间限制:
1s

内存限制:
128MB

题目描述:
最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功。所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力。
不妨设
A n = s i n ( 1 – s i n ( 2 + s i n ( 3 – s i n ( 4 + . . . s i n ( n ) ) . . . ) An=sin(1–sin(2+sin(3–sin(4+...sin(n))...) An=sin(1–sin(2+sin(3–sin(4+...sin(n))...)

S n = ( . . . ( A 1 + n ) A 2 + n − 1 ) A 3 + . . . + 2 ) A n + 1 Sn=(...(A1+n)A2+n-1)A3+...+2)An+1 Sn=(...(A1+n)A2+n1)A3+...+2)An+1
FJ想让奶牛们计算 Sn 的值,请你帮助FJ打印出 Sn 的完整表达式,以方便奶牛们做题。

输入描述:
仅有一个数:N < 201

输出描述:
请输出相应的表达式 Sn,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。

样例输入:

3

样例输出:

((sin(1)+3)sin(1-sin(2))+2)sin(1-sin(2+sin(3)))+1

解题思路

本题可以分别构造两个函数,将两者表示即可,其中对于 An,其函数表示为:

def A(n):
    # res 用来记录 An 结果
    res = ''
    for i in range(1, n+1):
        res += 'sin(' + str(i)
        if i != n:
            if i%2 != 0:
                res += '-'
            else:
                res += '+'

    # 结尾的 n 个反括号
    res += ')' * n
    return res

而对于 Sn 有:

def S(n):
    # res 用来记录 Sn 的结果
    res = ''
    # 开头的 n-1 个正括号
    res += '(' * (n-1)

    for i in range(1, n+1):
        res += str(A(i)) + '+' + str(n-i+1)
        if i != n:
            res += ')'

    return res

之后就直接利用这两个函数即可。


参考代码

def A(n):
    # res 用来记录 An 结果
    res = ''
    for i in range(1, n+1):
        res += 'sin(' + str(i)
        if i != n:
            if i%2 != 0:
                res += '-'
            else:
                res += '+'

    # 结尾的 n 个反括号
    res += ')' * n

    return res

def S(n):
    # res 用来记录 Sn 的结果
    res = ''
    # 开头的 n-1 个正括号
    res += '(' * (n-1)

    for i in range(1, n+1):
        res += str(A(i)) + '+' + str(n-i+1)
        if i != n:
            res += ')'

    return res

if __name__ == '__main__':
    n = int(input())
    print(S(n))

🐯 完美的代价

来源:🏆 Python | 蓝桥杯进阶第一卷——字符串

题目:
时间限制:
1s

内存限制:
128MB

题目描述:
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如:对于 mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)

输入描述:
第一行是一个整数 N,表示接下来的字符串的长度(N < = 8000)
第二行是一个字符串,长度为 N,只包含小写字母

输出描述:
如果可能,输出最少的交换次数。
否则输出 Impossible

样例输入:

5
mamad

样例输出:
3


解题思路

本题利用双指针,其中头指针 head 从前向后遍历,尾指针 tail 从后向前遍历。

退出循环的条件:

  • 字符串长度为偶数,但是有频数为奇数的字母
  • 字符串长度为奇数,但是有多于 1 个的频数为奇数的字母

具体思路见参考代码。

参考代码

n = int(input())
s = list(input())
count = 0   # 记录交换次数
flag = 0    # 标记是否有字母频数为奇数
res = True	# 标记是否为Impossible(是Impossible置为False)

# 双指针
L = n - 1   # 头指针搜索范围,到倒数第2个
for head in range(L):
    # 对于每一个s[head],用尾指针去搜索是否有相同的字母s[tail]
    for tail in range(L, head - 1, -1):
        # 指针tail搜索完毕,没有发现s[head] == s[tail]
        # 说明该字母频数为奇数 1,且该字母在回文序列中一定在中间
        if head == tail:
            # 如果字符串长度为偶数
            # 字符串长度为奇数,但是已经有 flag == 1
            if n%2 == 0 or flag == 1:
                res = False
                break
            flag = 1
            # (n//2 - head) 为将该字母移动到中间位置的交换次数
            count += n//2 - head
        # 发现了 s[head] == s[tail]
        elif s[head] == s[tail]:
            # 交换位置
            for i in range(tail, L):
                s[i], s[i+1] = s[i+1], s[i]
                count += 1
            L -= 1
            break

    # 如果是impossible,退出外层循环
    if res == False:
        break

if res == False:
    print('Impossible')
else:
    print(count)

🐧 字符串展开

来源:🏆 Python | 蓝桥杯进阶第一卷——字符串

题目:
时间限制:
1s

内存限制:
128MB

题目描述:
在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于 d-h 或者 4-8 的字串,我们就把它当作一种简写,输出时,用连续递增的字母获数字串替代其中的减号,即,将上面两个子串分别输出为 defgh45678。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:

  • 遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号 -,减号两侧同为小写字母或同为数字,且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。
  • 参数p1:展开方式。p1=1 时,对于字母子串,填充小写字母;p1=2 时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3 时,不论是字母子串还是数字字串,都用与要填充的字母个数相同的星号 * 来填充。
  • 参数p2:填充字符的重复个数。p2=k表示同一个字符要连续填充 k 个。例如,当 p2=3 时,子串d-h 应扩展为 deeefffgggh。减号两边的字符不变。
  • 参数p3:是否改为逆序:p3=1 表示维持原来顺序,p3=2 表示采用逆序输出,注意这时候仍然不包括减号两端的字符。例如当p1=1p2=2p3=2时,子串 d-h 应扩展为 dggffeeh
  • 如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如:d-e 应输出为 de3-4 应输出为 34。如果减号右边的字符按照 ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如:d-d 应输出为 d-d3-1 应输出为 3-1

输入描述:
输入包括两行:
1 行为用空格隔开的 3 个正整数,一次表示参数 p1p2p3
2 行为一行字符串,仅由数字、小写字母和减号 - 组成。行首和行末均无空格。

数据规模和约定
100%的数据满足:1<=p1<=31<=p2<=81<=p3<=2。字符串长度不超过 100

输出描述:
输出只有一行,为展开后的字符串.

样例输入:

1 2 1
abcs-w1234-9s-4zz

样例输出:
abcsttuuvvw1234556677889s-4zz


解题思路

  • 符号 - 只会在 s[1:len(s)-1] 之间(s 为输入字符串),因此要在这个范围内遍历,找到符号 - 并将其展开;
  • 满足展开的条件,即要判断左右两边的字符的ASCII码关系;
  • 之后根据 p3->p1->p2 的判断顺序对展开字符进行修改。

具体见代码。

参考代码

p1, p2, p3 = map(int, input().split())
s = input()
res = s[0]
# '-' 只会在s[1:len(s)-1]中间,因此s的首尾不需要变化
for i in range(1, len(s)-1):
    left, mid, right = s[i-1], s[i], s[i+1]
    # 遇到 '-' 并且左右字符满足如下条件:
    # 条件1:left<right
    # 条件2:(left>='0' and right<='9') or (left>='a' and right<='z') 
    if mid == '-' and left < right and ((left >= '0' and right <= '9') or (left >= 'a' and right <= 'z')):
        ## 判断顺序:p3 -> p1 -> p2
        ## p3
        if p3 == 1:
            # 顺序
            index_j = [j for j in range(ord(left)+1, ord(right))]
        else:
            # 逆序
            index_j = [j for j in range(ord(right)-1, ord(left), -1)]
        
        ## p1
        for j in index_j:
            # chr()转为字符
            tmp = chr(j)
            if p1 == 2:
                # 变为大写
                tmp = tmp.upper()
            elif p1 == 3:
                # 变为 '*'
                tmp = '*'
            
            ## p2
            # 重复 p2 次
            res += tmp * p2
    else:
            res += mid

# 尾巴
res += s[-1]
print(res)

🌴 Huffman树

来源:🔎 Python | 蓝桥杯进阶第二卷——贪心

题目:
时间限制:
3s

内存限制:
192MB

题目描述:
Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。

给出一列数 pi=p0, p1, …, pn-1,用这列数构造Huffman树的过程如下:

  1. 找到 pi 中最小的两个数,设为 papb,将 papbpi 中删除掉,然后将它们的和加入到 pi 中。这个过程的费用记为 pa + pb

  2. 重复步骤1,直到 pi 中只剩下一个数。

在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。

本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。

例如,对于数列 pi=5, 3, 8, 2, 9,Huffman树的构造过程如下:

  1. 找到 5, 3, 8, 2, 9 中最小的两个数,分别是 23,从 pi 中删除它们并将和 5 加入,得到 5, 8, 9, 5,费用为 5

  2. 找到 5, 8, 9, 5 中最小的两个数,分别是 55,从 pi 中删除它们并将和 10 加入,得到8, 9, 10,费用为 10

  3. 找到 8, 9, 10 中最小的两个数,分别是 89,从 pi 中删除它们并将和 17 加入,得到 10, 17,费用为 17

  4. 找到 10, 17 中最小的两个数,分别是 1017,从 pi 中删除它们并将和 27 加入,得到 27,费用为 27

  5. 现在,数列中只剩下一个数 27,构造过程结束,总费用为 5+10+17+27=59

输入描述:
输入的第一行包含一个正整数 n(n< =100)

接下来是 n 个正整数,表示 p0, p1, …, pn-1,每个数不超过 1000

输出描述:
输出用这些数构造Huffman树的总费用。

样例输入:

5 
5 3 8 2 9

样例输出:
59


解题思路

排序后循环 n-1 次,每次选出前两个(最小值),计算其和后,再加入列表中,并将这两个最小值删除。

参考代码

n = int(input())
nums = list(map(int, input().split()))
res = 0
nums.sort()

for i in range(n-1):
    total = nums[0] + nums[1]
    nums.append(total)
    res += total
    nums.pop(0)
    nums.pop(0)
    nums.sort()
print(res)

🍁 2^k进制数

来源:💝 Python | 蓝桥杯进阶第三卷——动态规划

题目:
时间限制:
1s

内存限制:
128MB

题目描述:
r r r 是个 2 k 2^k 2k 进制数,并满足以下条件:

  • r r r 至少是个 2 2 2 位的 2 k 2^k 2k 进制数。
  • 作为 2 k 2^k 2k 进制数,除最后一位外, r r r 的每一位严格小于它右边相邻的那一位。
  • r r r 转换为 2 2 2 进制数 q q q 后,则 q q q 的总位数不超过 w w w

在这里,正整数 k ( 1 ≤ k ≤ 9 ) k(1≤k≤9) k(1

html总结(常用插件,补充知识,经典例题)

常用(软件)插件:

1.http://v3.bootcss.com/css/(Bootstrap中文手册)<link rel="stylesheet" href="bootstrap-3.3.7/css/bootstrap.min.css">

2.http://jquery.cuishifeng.cn/   (jQuery中文手册)    <script src="jquery-3.2.1.js"></script>  <script src="bootstrap-3.3.7/js/bootstrap.min.js"></script>

3.[Font Awesome](http://fontawesome.io/)(图标手册) <link rel="stylesheet" href="font-awesome/css/font-awesome.min.css">

4.[jQuery lazy load](https://github.com/tuupola/jquery_lazyload) 5.[SweetAlert](https://github.com/t4t5/sweetalert)/[SweetAlert2](https://github.com/limonte/sweetalert2)  <link rel="stylesheet" href="sweetalert2/sweetalert2.min.css">

6.[Toastr](http://codeseven.github.io/toastr/)   http://thevectorlab.net/flatlab/toastr.html <link rel="stylesheet" href="toastr/toastr.min.css">

 

以上是关于总结+经典例题重做的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯算法竞赛系列第四章——二分算法

蓝桥杯 算法提高 学霸的迷宫 经典BFS问题

Python蓝桥杯易错点整理和心得总结

蓝桥杯之算法模板题 Python版

[蓝桥杯Python]算法练习算法基础算法训练算法模板(持续更新)

Java在算法竞赛中的技巧(蓝桥杯备赛总结)