小技巧:
1.要善于总结,多写文章、概括(便于之后的查询)
2.遇到编程题理不清思路?尝试模拟样例,用样例输入求出输出的过程中逐渐理清代码要完成的流程。(由具体到抽象)
3.编写程序时突然脑子糊涂了。可尝试带几组具体值理清思路.
4。编写程序不知晓如何正确的按顺序编写代码,不妨将要实现的目的及需要的步骤罗列出来,先分别写达成各个步骤需要的代码,最后将每小节代码合并成一个初步的函数。若有时间,将可能可以优化的步骤标注出并写下自己的想法。
下面以蓝桥杯2117题 砍竹子为例,题目网址为:
用户登录https://www.lanqiao.cn/problems/2117/learning/
一.分析:
总目的:计算总共要砍的次数-------计数器 sum+=1
从题目要求出发可参考的角度:
(1)由题目分析知计数(砍竹子次数)有条件:
1.高度相同、连续的竹子可用魔法一起砍去(注意要两个条件都满足):
判断高度相同:将高度存储起来
判断连续:索引值仅相差1
2.部分竹子需砍不止一次------要将砍后的高度存储起来:
未方便之后调用,保存后要能够通过第几次砍前/后的高度 、 具体的高度值-------可利用二维数组,设为f[i][j]
3.综合(1)(2)两点,每次砍完都要判断,但由于不同的竹子高度不同,需要砍的次数不同,而我们要判断的是同一时间点竹子高度相同,起始高度对应的j索引不应该为0,而应该是倒序赋值,以最后一次砍前的高度为j==0时的值。
4.题目要求最少次数,故要使的魔法能作用的对象增多,可想而知应先砍最高的数(模拟时需要,可不用)(若从光从题目中未能发现这一规律,从样例中也能察觉,要提高自身对这些规律的灵敏度)
(2)可知竹子砍后的高度要用到向下取整,取平方根
则导入模块 math 调用 floor(向下取整) sqrt(取平方根)
二.理出步骤:
1.不考虑魔法,计算将竹子全砍为高度1的次数,总数记为ans
2.记录每根竹子砍后的高度
3.比较任意相邻的竹子,看是否有相同高度,有则ans -1
4.ans为最终答案
三.由条件编写代码
1.时间紧,无充足时间深挖条件
采用暴力解法:
from math import *
n = int(input())
a = list(map(int,input().split()))
ans = 0
while True:
idx = 0
#查询最大值
for i in range(n):
if a[i]>a[idx]: idx = i
if a[idx] ==1 : break #全部为1m,退出循环
#存储最大值的值,用于之后判断是否只有一个值为val的最大值,a[idx]值将变化
val = a[idx]
for i in range(idx,n):
#如果第一个最大值不连续,则砍了后(a[idx] ==val满足条件]找下一个最大值
if a[i]!= val : break
a[i] = floor((sqrt(floor(a[i]/2)+1))
ans +=1 #将连续的最大值砍去
print(ans)
该代码多次遍历列表,时间复杂度大于O(n**2) ,会超时
2.利用二维数组
from math import *
f = [[0]*10 for i in range(20010)]
stk = [0]*10
n = int(input()) #输入玉米数量
a = list(map(int,input().split())) #输入玉米高度
ans = 0
for i in range(n):
x=a[i] ;top = 0
while x>1: #取高于1的玉米
top +=1;stk[top] = x #计算砍第i棵玉米要砍的次数,存储玉米高度砍第top次后的高度
x = floor(sqrt(floor(x/2)+1))
ans +=top #计算不用魔法,玉米总共要砍的次数
k = top ; j=0 #k为该棵玉米总共砍的次数
while k>0: f[i][j] = stk[k] ;k -=1 ; j +=1 #倒序存储第k次砍前的高度,i表示第几棵玉米
for j in range(10):
for i in range(1,n):
if f[i][j]>0 and f[i][j] == f[i-1][j]:
ans-=1
print(ans)