蓝桥杯-分类题型整理

在这里插入图片描述

DFS

在这里插入图片描述

迷宫(填空题)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
算法思路:深度dfs递归
在这里插入图片描述

map = ['UDDLUULRUL',
       'UURLLLRRRU',
       'RRUURLDLRD',
       'RUDDDDUUUU',
       'URUDLLRRUU',
       'DURLRLDLRL',
       'ULLURLLRDU',
       'RDLULLRDDD',
       'UUDDUDUDLL',
       'ULRDLUURRR']#这里字符串元素要用单引号括起,用双引号,后面会提示数组越界
count = 0
tablist = [[0] * 10 for i in range(10)]


def find(x, y):
    if x < 0 or x > 9 or y < 0 or y > 9:  # 走出迷宫
        global count
        count += 1
        return True

    if tablist[x][y] == 1:  # 已走过
        return False

    tablist[x][y] = 1  # 若之前没走过,则标记走过

    if map[x][y] == "U":
        find(x - 1, y)#递归
    elif map[x][y] == "D":
        find(x + 1, y)
    elif map[x][y] == "L":
        find(x, y - 1)
    elif map[x][y] == "R":
        find(x, y + 1)
    return False


for i in list(range(10)):
    for j in list(range(10)):
        tablist = [[0] * 10 for i in range(10)]#遍历每个坐标起点开始前都先清零
        find(i, j)

print(count)#答案31

承压计算(填空题)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
算法思路:将数据存到二维数组中,遍历求解对应的值,单位换算输出结果。
在这里插入图片描述

arr=[[0 for _ in range(30)] for _ in range(30)]#初始化30*30的二维数组存数据
k=0
file=open('data.txt','r')
for line in file.readlines():#注意这里有多个s
    line.strip()#去掉头尾空格
    new_line=line.split()#分割
    for i in range(len(new_line)):#分割后,字符串转为整数存
        arr[k][i]=int(new_line[i])
    k+=1
for i in range(1,30):#遍历,计算每一个数值
    for j in range(29):
        w = ((arr[i-1][j]) / 2)
        arr[i][j] += (w)
        arr[i][j+1] += (w)
print(2086458231/min(arr[29])*max(arr[29]))#单位换算

方格分割(填空题)

在这里插入图片描述
在这里插入图片描述
算法思想:从中心点开始沿四个方向找(x,y)与(6-x,6-y)是对称的,两个当做起点,都标记1表示经过,递归深度搜索四个方向,搜索中走到边界,说明分割完毕,类别数+1并返回,两个点置0,从另外的点开始遍历。最终递归回来,搜索结束,结果要除4,因为选择对称属于同一分割方法。
在这里插入图片描述

dx=[1,0,-1,0]
dy=[0,1,0,-1]
ans=0
map=[[0 for i in range(7)] for _ in range(7)]
def DFS(x,y):
    if x==0 or x==6 or y==0 or y==6:
        global ans
        ans+=1
        return
    for i in range(4):
        newx=x+dx[i]
        newy=y+dy[i]
        # print(newx,newy)
        if map[newx][newy]==0:
            map[newx][newy]=1#标记走过
            map[6-newx][6-newy]=1
            DFS(newx,newy)
            map[newx][newy]=0#搜索完后没走过
            map[6-newx][6-newy]=0

def main():
    map[3][3] = 1#从中心位置3,3开始
    DFS(3, 3)#深度搜索
    print(ans / 4)
if __name__=='__main__':
    main()

calendar库

  • calendar.weekday(y,m,d)可以返回这个年月日对应的星期

日期问题

在这里插入图片描述
在这里插入图片描述
算法思路:
1.利用Python中的try-except机制能更好地筛掉不符合的日期,避免写代码判断闰年2月的问题;
2.学会使用calendar标准库中方法。
注释中写了一些代码小技巧。

import calendar
date=input().split('/')#字符分割
res=[]
#遍历题目说的三种情况,若组合出的年月日不合法,※ 就使用try-except:pass
for u,v,w in [[0,1,2],[2,0,1],[2,1,0]]:
    for i in ['19','20']:
        year=int(i+date[u])
        if 1959<year<2060:
            try:
                calendar.weekday(year,int(date[v]),int(date[w]))
                res.append(f"{year}-{date[v]}-{date[w]}")
                #※ f-string用大括号 {} 表示被替换字段,其中直接填入替换内容
            except ValueError:
                pass
#res存放结果,后排序
res=list(set(res))#去重
res.sort(key=lambda data_:(data_[:4],data_[4:6],data_[6:]))#※ 先按照第一个元素排序,默认升序
print(*res,sep='\n')#※ 在形参前加'*'表示可以接受多个实参值存进数组,sep指分割符

BFS

迷宫

在这里插入图片描述

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

在这里插入图片描述

from collections import deque
ls = []
with open("./data.txt") as fp:
    for line in fp.readlines():
        ls.append(list(line.strip()))
rows, cols = len(ls), len(ls[0])
visit = [[False] * cols for _ in range(rows)]

queue = deque()
queue.append((0, 0, ""))
while queue:
    x, y, path = queue.popleft()
    if x == rows - 1 and y == cols - 1:
        print(path)
        break

    directs = ["R", "D", "L", "U"]
    for i, (dx, dy) in enumerate([(0, 1), (1, 0), (0, -1), (-1, 0)]):
        x1, y1 = x + dx, y + dy
        if -1 < x1 < rows and -1 < y1 < cols and ls[x1][y1] == '0' and not visit[x1][y1]:
            queue.append((x1, y1, path + directs[i]))
            visit[x1][y1] = True
data = '''01010101001011001001010110010110100100001000101010
          00001000100000101010010000100000001001100110100101
          01111011010010001000001101001011100011000000010000
          01000000001010100011010000101000001010101011001011
          00011111000000101000010010100010100000101100000000
          11001000110101000010101100011010011010101011110111
          00011011010101001001001010000001000101001110000000
          10100000101000100110101010111110011000010000111010
          00111000001010100001100010000001000101001100001001
          11000110100001110010001001010101010101010001101000
          00010000100100000101001010101110100010101010000101
          11100100101001001000010000010101010100100100010100
          00000010000000101011001111010001100000101010100011
          10101010011100001000011000010110011110110100001000
          10101010100001101010100101000010100000111011101001
          10000000101100010000101100101101001011100000000100
          10101001000000010100100001000100000100011110101001
          00101001010101101001010100011010101101110000110101
          11001010000100001100000010100101000001000111000010
          00001000110000110101101000000100101001001000011101
          10100101000101000000001110110010110101101010100001
          00101000010000110101010000100010001001000100010101
          10100001000110010001000010101001010101011111010010
          00000100101000000110010100101001000001000000000010
          11010000001001110111001001000011101001011011101000
          00000110100010001000100000001000011101000000110011
          10101000101000100010001111100010101001010000001000
          10000010100101001010110000000100101010001011101000
          00111100001000010000000110111000000001000000001011
          10000001100111010111010001000110111010101101111000'''
data_array = []
data_array.append([1]*52)
for i in data.split():
    data_array.append([])
    data_array[-1].append(1)
    for j in i:
        data_array[-1].append(int(j))
    data_array[-1].append(1)
data_array.append([1]*52)
visited = []  # 用来存放已经走过的点
queue = [[(1, 1)]]
start = (1, 1)
end = (30, 50)
visited.append(start)
def bfs(lst, queue, end):
    """
    广度优先搜索
    :param lst: 数据
    :param queue: 队列
    :param end: 终点坐标
    :return:
    """
    if end in queue[-1]:
        return queue
    alist = []
    for now in queue[-1]:
        row, col = now
        if lst[row+1][col] == 0 and ((row+1, col) not in visited):
            alist.append((row+1, col))
            visited.append((row+1, col))
        if lst[row][col+1] == 0 and ((row, col+1) not in visited):
            alist.append((row, col+1))
            visited.append((row, col+1))
        if lst[row-1][col] == 0 and ((row-1, col) not in visited):
            alist.append((row-1, col))
            visited.append((row-1, col))
        if lst[row][col-1] == 0 and ((row, col-1) not in visited):
            alist.append((row, col-1))
            visited.append((row, col-1))
    queue.append(alist)
    return bfs(lst, queue, end)
queue = bfs(data_array, queue, end)
Stack = []
Stack.append(start)
visited_1 = [start]
while Stack[-1] != end:
    now = Stack[-1]
    row, col = now
    i = queue[len((Stack))]
    """由于是D<L<R<U,所以尝试先走D,在走L,其次是R,U"""
    if (row+1, col) in i and (row+1, col) not in visited_1:
        Stack.append((row+1, col))
        visited_1.append((row+1, col))
        continue
    elif (row, col-1) in i and (row, col-1) not in visited_1:
        Stack.append((row, col-1))
        visited_1.append((row, col-1))
        continue
    elif (row, col+1) in i and (row, col+1) not in visited_1:
        Stack.append((row, col+1))
        visited_1.append((row, col+1))
        continue
    elif (row-1, col) in i and (row-1, col) not in visited_1:
        Stack.append((row-1, col))
        visited_1.append((row-1, col))
        continue
    else:
        """如果走不下去了,就返回"""
        Stack.pop()
length_1 = len(Stack)
strstep = ""
for i in range(1,length_1):
    if Stack[i][0] > Stack[i-1][0]:
        strstep += "D"
    elif Stack[i][0] < Stack[i-1][0]:
        strstep += "U"
    elif Stack[i][1] > Stack[i-1][1]:
        strstep += "R"
    else:
        strstep += "L"
print(strstep)

最终答案:

DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR

其他

包子凑数

在这里插入图片描述
在这里插入图片描述
算法思想:背包问题。考数学。
互质(最大公约数为1)说明有有限个解,进一步用数组统计,求有多少解。反之不互质说明有无限多个解,推理无解也有无限个。
在这里插入图片描述

def gcd(a,b):
    if b==0:
        return a
    return gcd(b,a%b)

n=int(input())
a=[0]
f=[False for i in range(10000)]
f[0]=True
for i in range(1,n+1):
    a.append(int(input()))
    if i==1:
        g=a[i]#初始化最大公约数
    else:
        g=gcd(a[i],g)#求最大公约数
    for j in range(10000):
        if j+a[i]>=10000:#防止越界
            break
        if f[j]:#若这个数能计算,则他加上后这样的也能算
            f[j+a[i]]=True
if g!=1:
    print("INF\n")
    exit()
ans=0
for i in range(10000):
    if not f[i]:
        ans+=1
        #print(i)
print(ans)

K倍区间

在这里插入图片描述
在这里插入图片描述
算法思路:数学技巧。
暴力遍历会超时,求i到j的区间,可以求s[j]-s[i],看是不是k倍数,可%k。数学转换下变为(s[i]-s[j])%k=0,s[i]%k=s[j]%k表示为k倍。从有n个相同值区间中选择两个,表示这个k倍区间数目。
在这里插入图片描述

n,k=map(int,input().split())#n个数,k倍
a,s=[0],[0 for i in range(k)]#a存输入值,s下标表示对应的和,s的值表示这个和的个数
res=0
temp_sum=[0]#前缀和取余k,第0个数不用
for i in range(1,n+1):
    a.append(int(input()))
    temp_sum.append((temp_sum[i-1]+a[i])%k)#求和,与前一个数相加
    s[temp_sum[i]]+=1#次数加1
for i in range(len(s)):#字典的值是出现的次数,对次数进行操作
    res+=s[i]*(s[i]-1)//2#s[i]个里任选两个,刚开始有n种选法,后面有n-1种,去掉重复/2
print(res+s[0])#还要加上自身到自身的区间s[0]

完全二叉树的权值

在这里插入图片描述
在这里插入图片描述
参考代码图解

#满二叉树前(n+1)层节点之和(n从0开始)
def deep(n):
    return (2**(n+1)-1)

#判断是否为满二叉树,如果是的话,不操作,否则将其补满为一棵满二叉树
def isfulltree(slist):
    deep_list=[] #每添加一层,的节点数
    for i in range(17): #2**17=131071>100000
        deep_list.append(deep(i))
    for i in range(len(deep_list)):
        if len(slist)==deep_list[i]:
            # num=1
            pass
        else:
            if len(slist)<deep_list[i] and len(slist)>deep_list[i-1]:
                for j in range(len(slist),deep_list[i]):
                    slist.append(0)
    return slist

#列表前n项和
def sum_list(slist,n): 
    sum=0
    for i in range(n):
        sum+=slist[i]
    return sum

#找出列表里最大的数的下标
def max_address(slist):
    index=0
    for i in range(len(slist)):
        if slist[i]>slist[index]:
            index=i
    return index+1

def main():
    n=int(input())
    slist=list(map(int,input().split()))
    slist=isfulltree(slist)
    lists=[] #每层权值
    n=0
    while deep(n)<=len(slist) :
        sum=0
        sum+=sum_list(slist,deep(n))
        lists.append(sum)
        for i in range(deep(n)):
            slist[i]=0
        n+=1
    maxs=max_address(lists)
    print(maxs)

main()

等差数列

在这里插入图片描述
在这里插入图片描述
算法思想:数学,求公倍数,等差

def gcd(x,y):#求最小公倍数
    while y:
      x,y=y,x%y
    return x
n=int(input())
a=list(map(int,input().split()))#输入转为整数
a.sort()#排序
s=[]#存两数的差
k=max(a)-min(a)
for i in range(n-1):
  s.append(a[i+1]-a[i])#两个数的差
s.sort()#数的差,排序
d=min(s)
if d==0:#有一样的数
  res=n
else:
  d=gcd(s[0],s[1])
  for i in range(3,len(s)):
    d=gcd(d,s[i])
  res=k//d+1#最大的差除公倍数+1
print(res)

后缀表达式

在这里插入图片描述
在这里插入图片描述

算法思想:在这里插入图片描述
在这里插入图片描述

from collections import deque
n,m=map(int,input().split())
s=[int(i) for i in input().split()]
s.sort()
def solve(n,m):
    if m==0: return sum(s)
    if n==0: return s[1]-(s[0]-sum(s[2:]))
    ans=0
    for i in s:
        ans+=abs(i)
    if s[0]>=0: return ans-2*s[0]
    if s[len(s)-1]<=0: return s[len(s)-1]+(ans-abs(s[len(s)-1]))
    return ans
print(solve(n,m))
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值