蓝桥杯第18天(Python版)(疯狂刷题篇第1天)

题型:

1.思维题/杂题:数学公式,分析题意,找规律

2.BFS/DFS:广搜(递归实现),深搜(deque实现)

3.简单数论:模,素数(只需要判断到 int(sqrt(n))+1),gcd,lcm,快速幂(位运算移位操作),大数分解(分解为质数的乘积)

4.简单图论:最短路(一对多(Dijstra,临接表,矩阵实现),多对多(Floyd,矩阵实现)),最小生成树(并查集实现)

5.简单字符串处理:最好转为列表操作

6.DP:线性DP,最长公共子序列,0/1背包问题,最长连续字符串,最大递增子串

7.基本算法:二分,贪心,组合,排列,前缀和,差分

8.基本数据结构:队列,集合,字典,字符串,列表,栈,树

9.常用模块:math,datetime,sys中的设置最大递归深度(sys.setrecursionlimit(3000000)),collections.deque(队列),itertools.combinations(list,n)(组合),itertools.permutations(list,n)(排列)  heapq(小顶堆)

目录

真题刷题

1.大学的树木要打药(差分)

2.大学里的树木要维护(前缀和)

3.成绩统计(简单判断)

4.排列字母(排序)

5.纸张尺寸 (循环语句)

6.特殊时间(思维题,根据要求手算枚举)

 7.卡片问题(思维题,拼数看哪张卡牌用得最快)

8.约数个数(考察概念)

9.美丽的区间(暴力法+sum函数或者双指针或者暴力+前缀和)

10.回文判定(字符串切片或者转为列表切片)

11.数的计算(递归,重点在于边界处理以及初始值设定)

12.数的划分(DP,递推,完备集拆分找递推关系)

 13.迷宫(BFS+DFS)

14.跳蚂蚱(BFS,自定义入队元素格式,画圆为直)

15.七段码(画图数)

16.走迷宫(BFS,入队信息包括距离)

17.N皇后问题


真题刷题

1.大学的树木要打药(差分)

 差分做法

import sys
import collections
import itertools
import heapq

n,m=map(int,input().split())
a=[0 for i in range(n+1)]  # 编号1-n
b =[0]+[a[i+1]-a[i] for i in range(0,n)] # 差分数组,编号1-n

for i in range(m):   # 整体区间操作直接对差分数组修改
    l,r,cost = map(int,input().split())
    b[l]+=cost;b[r+1]-=cost

for i in range(1,n+1):  # 根据差分数组重新还原数组
    a[i]=a[i-1]+b[i]
    
print(sum(a))

2.大学里的树木要维护(前缀和)

 

import sys
import collections
import itertools
import heapq

n,m=map(int,input().split())  # 马路的树木,区间的数目
cost = list(map(int,input().split()))
Pre_sum=[0]  # 记录前缀和,编号从1开始
temp=0
for i in range(n):  # 记录前缀和
    temp+=cost[i]
    Pre_sum.append(temp)
    
for i in range(m):  # 通过前缀和计算
    l,r=map(int,input().split())
    print(Pre_sum[r]-Pre_sum[l-1])
    

3.成绩统计(简单判断)

 送分题,主要是判定条件,即两个判断计数就可以了,主要是格式输出

print("{:.2%}".format(n)),保留两位小数同时百分比形式输出

 format格式用法

4.排列字母(排序)

 也是送分题,主要是了解内置排序函数,列表 的sort(),可迭代对象sorted()方法

5.纸张尺寸 (循环语句)

送分题,主要是从输入提取信息,利用字符串切片,然后在循环减半,长宽互换。

        a,b=b,a

6.特殊时间(思维题,根据要求手算枚举)

考过的填空题不会再考,不写解答过程了,解题思路为只需要考虑月份和日期,小时和分钟

月:1-12

日:1-31

时:0-23

分:0-59

抓住3个相同手算枚举,主要是细心

 7.卡片问题(思维题,拼数看哪张卡牌用得最快)

 可以看出1是用的最快的,看不出的话打印一遍看谁用的最快,然后直接弄个死循环,卡片1用完了使用  break  跳出循环就可以了。

8.约数个数(考察概念)

 约数:即能被整除的数,包括1和本身,取余为0,因为是填空题,并且数据不是很大,所以可以直接循环,枚举[1,1200000],或者使用大数分解,分解为质数,然后算质数幂的组合数即可。

9.美丽的区间(暴力法+sum函数或者双指针或者暴力+前缀和

import sys
import collections
import itertools
import heapq

#暴力
n,s =(map(int, input().split()))
a = [0]+list(map(int,input().split())) # 下标从1开始
ans=100000
##for i in range(1,n+1):
##    for j in range(i+1,n+1):
##        if sum(a[i:j+1])>=s:
##            ans=min(ans,j+1-i)
##print(ans)


#双指针
##left=1
##right=1
##ss=0  #记录区间值
##while right<=n: 
##    if ss<s: # 右移动
##        ss+=a[right]
##        right+=1
##    #if ss>=s:
##    else:
##        print(right,left)
##        ans=min(ans,right-left)  # right 指向后一个位置,所以没有+1
##        ss-=a[left]
##        left+=1
##print(ans)
##        


# 前缀和加暴力
pre=[0]  #记录前缀和
ss=0
for i in range(1,n+1):
    ss+=a[i]
    pre.append(ss)
for i in range(1,n+1):
    for j in range(i+1,n+1):
        if (pre[j]-pre[i-1])>=s:
            ans=min(ans,j+1-i)
print(ans)

这道题通过3种方法进行解决,双指针是最好的解决方法,其次是前缀和,这道题就是考察编程能力,没有算法,就是暴力,学会利用双指针,快慢指针,前缀和进行解题。

10.回文判定(字符串切片或者转为列表切片)

 回文判断都是送分题,转为列表反序输出比较就可以。字符本身也可以切片,反正就是送分题!!!  str[::-1]    list[::-1]

11.数的计算(递归,重点在于边界处理以及初始值设定)

import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(100000)

# 6
# 16 26 36
#    126 136
def f(x):
    global ans
    if x==1 or x==0:
        return
    for i in range(1,x//2 +1):
        ans+=1
        f(i)
    
n=int(input())
ans=1  # 自身是一个
f(n)
print(ans)

递归解决,本题难点在于读懂题意,有点像是思维题,要注意边界处理,在函数中改变量记得声明为全局变量,同时注意初始值的设定,递归注意设置最大递归深度!!!

12.数的划分(DP,递推,完备集拆分找递推关系)

import sys
import collections
import itertools
import heapq
sys.setrecursionlimit(100000)


n, k = map(int, input().split())

# 初始化一个二维数组,用于存储 f(n, m)
dp = [[0 for j in range(210)] for i in range(210)]
for i in range(1, n+1):
   dp[i][1] = 1   # i个物品1个人分
   dp[i][i] = 1   # i个物品i个人分

for i in range(3, n+1):
   for j in range(2, k+1):
       if i > j:
           dp[i][j] = dp[i-j][j] + dp[i-1][j-1]  

print(dp[n][k])

感觉有问题,不是说任意两份不能相同吗??上面的做法是有相同的,题目有问题,应该问的是有多少种分法!!!通过dp进行求解

 13.迷宫(BFS+DFS)

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
import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq
sys.setrecursionlimit(100000)

s="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"


vis=[[0]*60 for _ in range(60)]  # 标记是否访问过
fa=[['']*60 for _ in range(60)]  # 记录父结点
flag=['D','L','R','U']  # ↓x → y
##a = list(s.split(' '))
##print(a)
##ss=[]
##for i in s:  #转为2维列表
##    ss.append(i)
##print(ss)
ss=[]
for i in range(30):
    ss.append(list(map(int,input())))


def dfs(x,y):  # 通过DFS遍历找路径
    if x==0 and y==0:
        return
    if fa[x][y]=='D':dfs(x-1,y)
    if fa[x][y] =='L': dfs(x,y+1)
    if fa[x][y] =='R': dfs(x,y-1)
    if fa[x][y] =='U': dfs(x+1,y)
    print(fa[x][y],end='')
    
def bfs(x,y):
    global fa
    global vis
    deque=collections.deque()
    walk=[[1,0],[0,-1],[0,1],[-1,0]]  # 下,左,右,上
    vis[x][y]=1
    deque.append((0,0))  # 添加进队列
    while deque:
        x,y=deque.popleft()
        #print(x,y)
        if x==29 and y==49:
            print("找到终点!!")
            break
        for index in range(4):
            dx,dy=walk[index]
            nx=x+dx;ny=y+dy
            if 0<=nx<=29 and 0<=ny<=49 :
                if vis[nx][ny]==0 and ss[nx][ny]==0: # 坐标合法且没有走过
                    vis[nx][ny]=1
                    deque.append((nx,ny))
                    fa[nx][ny]=flag[index]

bfs(0,0)    
dfs(29,49)

BFS,DFS的组合问题,遇到最短路径,最短路的时候一般用BFS,通过队列deque实现。对于这种格子问题,一般↓为x方向,→有y方向,记得将标记数组和记录数组设置大一点。

BFS是通过循环实现,DFS是通过递归实现。 

14.跳蚂蚱(BFS,自定义入队元素格式,画圆为直)

from collections import * 
def insertQueue(q: deque, dir: int, news: tuple, vis: set):
   pos = news[1];  status = news[0];  insertPos = (pos + dir + 9) % 9    
   t = list(status)
   t[pos], t[insertPos] = t[insertPos], t[pos]
   addStatus = "".join(t)
   if addStatus not in vis:
       vis.add(addStatus)
       q.append((addStatus, insertPos, news[2] + 1))  
q = deque()
q.append(("012345678", 0, 0))
vis = set();  vis.add("012345678")
while q:
   news = q.popleft()
   if news[0] == "087654321":      print(news[2]); break
   insertQueue(q, -2, news, vis);  insertQueue(q, -1, news, vis)
   insertQueue(q,  1, news, vis);  insertQueue(q,  2, news, vis)

BFS问题进队列的元素类型可以自己定义,一般是结合题目需要,比如说经过最少次数这些,结合题意,结合题意,结合题意。

15.七段码(画图数)

 手算题,根据亮灯数依次计算有多少种情况,通过画图自己数就行了。

16.走迷宫(BFS,入队信息包括距离)

import collections
mp = []   #存地图  n行m列
n,m = map(int,input().split())
for i in range(n):  # 读地图
    mp.append(list(map(int,input().split())))
x1,y1,x2,y2 = map(int,input().split())
dir = [(1,0),(0,-1),(0,1),(-1,0)]  # 下为x正方向,右为y正方向
vis = [[0]*200 for i in range(200)]  # 标记数组
ans = 0
flag=0
 
def bfs(x,y):
    global vis,ans,flag
    q = collections.deque()
    q.append((x,y,0)) # 遍历该点
    vis[x][y] = 1
    while q:
        now = q.popleft()
        if now[0]==(x2-1) and now[1] ==(y2-1) :# 到达终点(x2,y2)
            flag = 1
            ans=now[2]
            break
        for index in range(4):  # 4个方向遍历
            i=dir[index]
            nx = now[0]+i[0];ny = now[1]+i[1]
            if nx<0 or nx >=n or ny<0 or ny>=m : #超出了边界
                continue
            if vis[nx][ny]==1 or mp[nx][ny] ==0:  # 判断是否走过或者碰到了边界
                continue
            vis[nx][ny]=1
            q.append((nx,ny,now[2]+1))  # 将当前点添加进队列
bfs(x1-1,y1-1) # 从x1,y1搜索到x2,y2
if flag==0:
  print(-1)
else:
  print(ans)

 12题13题结合,就是通过BFS找到最少走多少个,入队元素格式中需要有每次的步数,每次入队列加一就可以了。

17.N皇后问题

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq
sys.setrecursionlimit(300000)

n=int(input())

#vis = [[0]*11 for i in range(10)]  # 标记数组,下标从1开始
vis = [0]*11   # 标记是否使用过该列
ans = 0
save = [0]*11  # 记录每行放的位置,下标从1开始


def check(i,m):
   if vis[i]==1:  # 检查是否同列
      return False
   for j in range(1,m):  #遍历前面m-1个看是否斜对角相同
      if abs(m-j) ==abs(i-save[j]):
         return False
   return True
   
def dfs(m): # m行
   global ans,vis, save
   if m==n+1:
      print('Find')
      print(*save)
      ans+=1
      return
   for i in range(1,n+1):  # 遍历n列找位置
      if check(i,m):
         save[m]=i  # 第m行放在i列
         vis[i]=1   # 使用过第i列
         dfs(m+1)
         vis[i]=0

dfs(1)
print(ans)

 我这里处理了下标,转为下标从1开始,更方便处理,这里的dfs,标记数组并没有用到二维,只用了一维来记录列,判断列是否用过,与前面摆放的是否斜边冲突。这里还用到了一个数组存储每次摆放的位置,判断是用到了来判断斜边,也可以打印输出路径。

DFS模板

vis=[ 0 ] * N  标记数组

def check()

        pass

def dfs()

        if  ( 达到退出条件或者终点 ):

                return

        for  i in choice:

             if check(i):

                保护现场

                dfs()

                恢复现场

猜你喜欢

转载自blog.csdn.net/weixin_52261094/article/details/129861955