目录
真题刷题
1.大学的树木要打药(差分)
2.大学里的树木要维护(前缀和)
3.成绩统计(简单判断)
4.排列字母(排序)
5.纸张尺寸 (循环语句)
6.特殊时间(思维题,根据要求手算枚举)
7.卡片问题(思维题,拼数看哪张卡牌用得最快)
8.约数个数(考察概念)
9.美丽的区间(暴力法+sum函数或者双指针或者暴力+前缀和)
10.回文判定(字符串切片或者转为列表切片)
11.数的计算(递归,重点在于边界处理以及初始值设定)
12.数的划分(DP,递推,完备集拆分找递推关系)
13.迷宫(BFS+DFS)
14.跳蚂蚱(BFS,自定义入队元素格式,画圆为直)
15.七段码(画图数)
16.走迷宫(BFS,入队信息包括距离)
17.N皇后问题
差分做法
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))
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])
送分题,主要是判定条件,即两个判断计数就可以了,主要是格式输出
print("{:.2%}".format(n)),保留两位小数同时百分比形式输出
format格式用法
也是送分题,主要是了解内置排序函数,列表 的sort(),可迭代对象sorted()方法
送分题,主要是从输入提取信息,利用字符串切片,然后在循环减半,长宽互换。
a,b=b,a
考过的填空题不会再考,不写解答过程了,解题思路为只需要考虑月份和日期,小时和分钟
月:1-12
日:1-31
时:0-23
分:0-59
抓住3个相同手算枚举,主要是细心
可以看出1是用的最快的,看不出的话打印一遍看谁用的最快,然后直接弄个死循环,卡片1用完了使用 break 跳出循环就可以了。
约数:即能被整除的数,包括1和本身,取余为0,因为是填空题,并且数据不是很大,所以可以直接循环,枚举[1,1200000],或者使用大数分解,分解为质数,然后算质数幂的组合数即可。
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:
## 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种方法进行解决,双指针是最好的解决方法,其次是前缀和,这道题就是考察编程能力,没有算法,就是暴力,学会利用双指针,快慢指针,前缀和进行解题。
回文判断都是送分题,转为列表反序输出比较就可以。字符本身也可以切片,反正就是送分题!!! str[::-1] list[::-1]
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)
递归解决,本题难点在于读懂题意,有点像是思维题,要注意边界处理,在函数中改变量记得声明为全局变量,同时注意初始值的设定,递归注意设置最大递归深度!!!
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进行求解
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是通过递归实现。
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问题进队列的元素类型可以自己定义,一般是结合题目需要,比如说经过最少次数这些,结合题意,结合题意,结合题意。
手算题,根据亮灯数依次计算有多少种情况,通过画图自己数就行了。
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找到最少走多少个,入队元素格式中需要有每次的步数,每次入队列加一就可以了。
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()
恢复现场