[蓝桥杯Python]算法练习算法基础算法训练算法模板(持续更新)
Posted Callme_TeacherPi℡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[蓝桥杯Python]算法练习算法基础算法训练算法模板(持续更新)相关的知识,希望对你有一定的参考价值。
[蓝桥杯Python]算法练习、算法基础、算法训练、算法模板(持续更新.....)
目录
一、算法基础
1.Huffuman树
问题描述:Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。给出一列数pi=p0, p1, …, pn-1,用这列数构造Huffman树的过程如下:
1. 找到pi中最小的两个数,设为pa和pb,将pa和pb从pi中删除掉,然后将它们的和加入到pi中。这个过程的费用记为pa + pb。
2. 重复步骤1,直到pi中只剩下一个数。
在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。
本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。
例如,对于数列pi=5, 3, 8, 2, 9,Huffman树的构造过程如下:
1. 找到5, 3, 8, 2, 9中最小的两个数,分别是2和3,从pi中删除它们并将和5加入,得到5, 8, 9, 5,费用为5。
2. 找到5, 8, 9, 5中最小的两个数,分别是5和5,从pi中删除它们并将和10加入,得到8, 9, 10,费用为10。
3. 找到8, 9, 10中最小的两个数,分别是8和9,从pi中删除它们并将和17加入,得到10, 17,费用为17。
4. 找到10, 17中最小的两个数,分别是10和17,从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 = int(input())
tab = input().split()
all_num = 0 #总成本
while len(tab) > 1: #需要进行n轮
# 找出最小的两个数
min_1 = int(tab[0])
for i in range(1, len(tab)):
if int(tab[i]) < min_1:
min_1 = int(tab[i])
tab.remove(str(min_1)) #去除第一个最小数
min_2 = int(tab[0])
for j in range(1, len(tab)):
if int(tab[j]) < min_2:
min_2 = int(tab[j])
tab.remove(str(min_2)) #去除第二个最小数
all_num += min_1 + min_2 #累加成本
tab.append(str(min_1 + min_2)) #将第一轮的成本加入列表中
print(all_num)
2.Sine之舞
问题描述:最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功。所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力。不妨设
An=sin(1–sin(2+sin(3–sin(4+...sin(n))...)
Sn=(...(A1+n)A2+n-1)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
'''
n = int(input())
A_n = ["sin(1)"]
for i in range(2,n+1):
if i%2 == 0:
A_n.append(A_n[i-2][:-(i-1)])
A_n[i-1] += "-"+"sin("+str(i)+")"*i
else:
A_n.append(A_n[i-2][:-(i-1)])
A_n[i-1] += "+"+"sin("+str(i)+")"*i
S_n = ""
for j in range(1,n):
if j%2 != 0:
S_n += A_n[j-1] + "+" + str(n+j-1) + ")"
else:
S_n += A_n[j-1] + "+" + str(n-j+1) + ")"
S_n = "("*(n-1) + S_n + A_n[n-1] + "+" + "1"
print(S_n)
3.数列排序
问题描述:给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
'''
输入格式
第一行为一个整数n。
第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式
输出一行,按从小到大的顺序输出排序后的数列。
样例输入
5
8 3 6 4 9
样例输出
3 4 6 8 9
'''
n = int(input())
s = input().split()
for i in range(n):
for j in range(n-i-1):
if int(s[j])>int(s[j+1]):
tmp = s[j+1]
s[j+1] = s[j]
s[j] = tmp
for i in range(n):
print(s[i],end=" ")
4.数列排序
问题描述:给定n个十六进制正整数,输出它们对应的八进制数。
'''
输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
输出n行,每行为输入对应的八进制正整数。
【注意】
输入的十六进制数不会有前导0,比如012A。
输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
'''
n = int(input())
record = []
for i in range(n):
record.append(input())
for i in range(n):
nn = int(record[i],16)
ss = oct(nn)
print(ss[2:])
5.特殊回文数
问题描述:123321是一个非常特殊的数,它从左边读和从右边读是一样的。输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
'''
输入格式
输入一行,包含一个正整数n。
输出格式
按从小到大的顺序输出满足条件的整数,每个整数占一行
样例输入
52
样例输出
899998
989989
998899
'''
n = int(input())
for i in range(10000,1000000):
z = str(i)
if z==z[::-1]:
m=sum(int(j) for j in z)
if m==n :
print(z)
6.回文数
问题描述:1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
'''
输出格式
按从小到大的顺序输出满足条件的四位十进制数。
'''
for i in range(1000,10000):
arr = str(i)
a,b,c,d = int(arr[0]) ,int(arr[1]) ,int(arr[2]) ,int(arr[3])
if(a^d == 0 and b^c == 0): #采用异或运算符,不懂得可以自己去搜索一下
print(i)
7.特殊的数字
问题描述:153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件的三位十进制数。
'''
输出格式
按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
'''
for i in range(100, 1000):
if ((int(str(i)[0]) * int(str(i)[0])* int(str(i)[0]) + int(str(i)[1]) * int(str(i)[1]) * int(str(i)[1])+ int(str(i)[2]) * int(str(i)[2])* int(str(i)[2])) == i):
print(i)
8.杨辉三角形
问题描述:杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。 它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。 下面给出了杨辉三角形的前4行:
1
1 1
1 2 1
1 3 3 1
'''
输入格式
输入包含一个数n
输出格式
输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。
样例输入
4
样例输出
1
1 1
1 2 1
1 3 3 1
'''
numRows = int(input())
ret = []
for i in range(numRows):
row = []
for j in range(i+1):
if(j == 0 or j == i):
row.append(1)
else:
row.append(ret[j]+ret[j-1])
for x in range(i+1):
print(row[x],end=" ")
print("\\t") #隔空输出
ret = row
9.高精度加法
问题描述:输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。
由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
最后将C输出即可。
'''
输入格式
输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。
输出格式
输出一行,表示a + b的值。
样例输入
20100122201001221234567890
2010012220100122
样例输出
20100122203011233454668012
'''
a = str(input())[::-1]
b = str(input())[::-1]
i = 0
read = 0
num = ""
j = min(len(a),len(b))
hashtab = [0]*(max(len(a),len(b))+1)
#补全
if len(a) > len(b):
while j < len(a):
hashtab[j] = a[j]
j += 1
else:
while j < len(b):
hashtab[j] = b[j]
j += 1
#相加
while i < min(len(a),len(b)):
if int(a[i])+int(b[i]) < 10:
hashtab[i] = str(int(a[i])+int(b[i]) + int(hashtab[i]))
else:
hashtab[i] = str((int(a[i]) + int(b[i])) % 10 + int(hashtab[i]))
hashtab[i+1] = str((int(a[i]) + int(b[i])) // 10 + int(hashtab[i+1]))
i += 1
#判断最高位是否进位
for o in range(0,len(hashtab)):
if int(hashtab[o]) >= 10:
hashtab[o + 1] = str(int(hashtab[o]) // 10 + int(hashtab[o + 1]))
hashtab[o] = str(int(hashtab[o]) % 10 )
#输出
while read < len(hashtab):
num += str(hashtab[read])
read += 1
#判断高位是否为0.如果是的话不输出
if num[-1] == "0":
num = num[::-1]
print(num[1:])
else:
print(num[::-1])
10.Fibonacci数列
问题描述:Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少。
'''
输入格式
输入包含一个整数n。
输出格式
输出一行,包含一个整数,表示Fn除以10007的余数。
样例输入
10
样例输出
55
'''
n = int(input())
f_1 = 1 #想最初的两个1,2求出来,后面我们直接从F(3)开始运算
f_2 = 1
if n==1:
num = 1
if n==2:
num = 1
m = 3
while m < n+1:
num = (f_1 + f_2) % 10007 #由于提示不用算出每个数,每次只用算出每个数对10007的余数就行
mid = f_1
f_1 = f_2 %10007
f_2 = (mid + f_1)%10007 #可以减少运算,否则可能运算超时
m += 1
print(num)
11.报时助手
问题描述:给定当前的时间,请用英文的读法将它读出来。
时间用时h和分m表示,在英文的读法中,读一个时间的方法是:
如果m为0,则将时读出来,然后加上“o'clock”,如3:00读作“three o'clock”。
如果m不为0,则将时读出来,然后将分读出来,如5:30读作“five thirty”。
时和分的读法使用的是英文数字的读法,其中0~20读作:
0:zero, 1: one, 2:two, 3:three, 4:four, 5:five, 6:six, 7:seven, 8:eight, 9:nine, 10:ten, 11:eleven, 12:twelve, 13:thirteen, 14:fourteen, 15:fifteen, 16:sixteen, 17:seventeen, 18:eighteen, 19:nineteen, 20:twenty。
30读作thirty,40读作forty,50读作fifty。
对于大于20小于60的数字,首先读整十的数,然后再加上个位数。如31首先读30再加1的读法,读作“thirty one”。
按上面的规则21:54读作“twenty one fifty four”,9:07读作“nine seven”,0:15读作“zero fifteen”。
'''
输入格式
输入包含两个非负整数h和m,表示时间的时和分。非零的数字前没有前导0。h小于24,m小于60。
输出格式
输出时间时刻的英文。
样例输入
0 15
样例输出
zero fifteen
'''
Time = input().split()
# 创建一个字典把特殊的读法放进去
dict = 0:'zero', 1: 'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen', 20:'twenty',21:'twenty one',22:'twenty two',23:'twenty three',24:'twenty four',30:'thirty',40:'forty',50:'fifty'
read_time = ''
read_time += dict[int(Time[0])] # 将h读出来
if int(Time[1]) == 0:
read_time += " o'clock"
elif 0<int(Time[1])<=24:
read_time +=" "
read_time += dict[int(Time[1])]
else:
read_time += " "
read_time += dict[int(Time[1])//10*10]
read_time += " "
read_time += dict[int(Time[1])%10]
print(read_time)
12.回形取数
问题描述:回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
'''
输入格式
输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出格式
输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3
1 2 3
4 5 6
7 8 9
样例输出
1 4 7 8 9 6 3 2 5
'''
mn = input().split()
m = int(mn[0])
n = int(mn[1])
rect = []
for x in range(0,int(mn[0])):
apend_rect = input().split()
rect.append(apend_rect)
result = ""
#总共需要取n//2+n%2
for z in range(0,min(m,n)//2+min(m,n)%2):
if m < 2 or n < 2:
if m==1 and n ==1:
result += " " + rect[0][0]
elif m < 2:
for i in range(0, n):
result += " " + rect[0][i]
else:
for i in range(0, m):
result += " " + rect[i][0]
else:
result += " " + rect[0][0]
# 取外圈的数
i, j = 0, 0
for y in range(0, m * n - (m - 2) * (n - 2)):
# 从左上角向下取
if i < m - 1 and j == 0:
i += 1
result += " " + rect[i][j]
# 从左下角向右取
elif i == m - 1 and j < n - 1:
j += 1
result += " " + rect[i][j]
# 从右下角向上取
elif i > 0 and j == n - 1:
i -= 1
result += " " + rect[i][j]
# 从右上角向左取
else:
while j > 1:
j -= 1
result += " " + rect[i][j]
#取内圈作为下一次外圈的输入
m -= 2
n -= 2
if m > 0 or n > 0:
rect_new = []
a = 1
while a < m+1:
rect_new_small = []
b = 1
while b < n+1:
rect_new_small.append(rect[a][b])
b += 1
rect_new.append(rect_new_small)
a += 1
rect = rect_new
print(result[1:])
13.矩阵乘法
问题描述:给定一个N阶矩阵A,输出A的M次幂(M是非负整数)
'''
输入格式
第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数
接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值
输出格式
输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开
样例输入
2 2
1 2
3 4
样例输出
7 10
15 22
'''
mn = input().split()
N = int(mn[0])
M = int(mn[1])
#导入矩阵
rect = []
for x in range(0,N):
apend_rect = input().split()
rect.append(apend_rect)
rect_new = [[ 0 for _ in range(0,N)] for _ in range(0,N)]
rect_mid = rect
if M == 0:
for i in range(0,N):
rect_new[i][i] = 1
result = ""
for j in range(0,N):
result += " " + str(rect_new[i][j])
print(result[1:])
else:
if M == 1:
rect_new = rect
else:
for i in range(0,M-1):
rect_new = [[0 for _ in range(0, N)] for _ in range(0, N)]
a = 0 #a为行计算,b为列计算
while a < N:
b = 0
while b < N:
for j in range(0,N):
rect_new[a][b] += int(rect_mid[a][j]) * int(rect[j][b])
b += 1
a += 1
rect_mid = rect_new
for i in range(0,N):
result = ""
for j in range(0,N):
result += " " + str(rect_new[i][j])
print(result[1:])
二、算法提高
1.印章
问题描述:共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
'''
输入格式
一行两个正整数n和m
输出格式
一个实数P表示答案,保留4位小数。
样例输入
2 3
样例输出
0.7500
'''
nm = list(map(int,input().split()))
n = nm[0]
m = nm[1]
rect = [[0 for _ in range(0,n)] for _ in range(0,m)]
#拥有一张时,拥有一张的概率必为1
rect[0][0] = 1
for i in range(1,m):
rect[i][0] = (1/n)**i
for i in range(1,m):
for j in range(1,n):
#第i-1张已经拥有j种+i-1张没有拥有第j种的概率
rect[i][j] = rect[i-1][j]*((j+1)/n) + rect[i-1][j-1]*((n-j)/n)
print("%.4f" % rect[-1][-1])
2.拿金币
问题描述:有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
'''
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
'''
n = int(input())
rect = []
for i in range(0, n):
rect.append(input().split())
rect[0][0] = int(rect[0][0]) #第一个只能(1,1)的自身
for i in range(1,n):
rect[0][i] = int(rect[0][i]) + int(rect[0][i-1])
for i in range(1, n):
rect[i][0] = int(rect[i][0]) + int(rect[i-1][0])
for i in range(1, n):
for j in range(1, n):
#(i,j)就是自身加上左边以及上面两个的最大值
rect[i][j] = int(rect[i][j]) + max(int(rect[i-1][j]),int(rect[i][j-1]))
#累加后最后一个就为最大值
print(rect[-1][-1])
3.B君的寄望
问题描述:B君在执行爬山计划的时候迷了路,但他身上有个哨子,而哨声分为长和短,中间要有间隔,短音1s,长音2s,间隔1s,给你总时间,问有几种吹法,最后一个哨声要刚好在第n秒时结束。
'''
输入格式
每组测资只有一个整数,1~1000
输出格式
输出一个整数,代表哨声吹法种数
样例输入
1
样例输出
1
'''
n = int(input())
if n < 5:
if n == 2 or n == 4:
print(0)
if n == 1:
print(1)
if n == 3:
print(2)
else:
rect = [[0,0] for _ in range(0,n)]
rect[0][0] = 1
rect[0][1] = 0
rect[1][0] = 0
rect[1][1] = 1
rect[2][0] = 1
rect[2][1] = 0
rect[3][0] = 1
rect[3][1] = 1
for i in range(4,n):
rect[i][0] = rect[i - 2][0] + rect[i - 2][1]
rect[i][1] = rect[i - 3][0] + rect[i - 3][1]
print(rect[-1][-1]+rect[-1][-2])
4.数字游戏
问题描述: 给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。
例如:
3 1 2 4
4 3 6
7 9
16
现在如果知道N和最后得到的数字sum,请求出最初序列a[i],为1~N的一个排列。若有多种答案,则输出字典序最小的那一个。数据保证有解。
'''
输入格式
第1行为两个正整数n,sum
输出格式
一个1~N的一个排列
样例输入
4 16
样例输出
3 1 2 4
'''
###首先声明这道题真的真的真的太难了....只得了三十分,其他结果没问题,但是运算超时....
In = input().split()
n = int(In[0]) #行数
num = int(In[1]) #最终总数
rect = [] #记录最终的排序
#计算三角函数第n行的每个数
def trangle(x):
trangle_rect = [[1],[1,1]]
for i in range(2,x):
mid = []
for j in range(0,i+1):
if j==0 or j==i:
mid.append(1)
else:
mid.append(trangle_rect[i-1][j] + trangle_rect[i-1][j-1])
trangle_rect.append(mid)
return trangle_rect[-1]
trangle_n = trangle(n)
mid = [] #记录过程中的数组
def trackback(n,s): #n=几行,starIndex=起始位置
#判断是否成功
if len(mid) > n:
return
game_over(s)
#回溯
for j in range(1,n+1):
mid.append(j)
trackback(n,j)
mid.pop()
#代码冗长单独写一个判断是否成功的函数
def game_over(s):
all_num = 0
#判断如果长度不同直接返回
if len(mid) == n:
for i in range(0,n):
all_num += int(trangle_n[i]) * int( mid[i])
if all_num == num:
mid_set = set(mid)
#判断是否有重复的数
if len(mid_set) != len(mid):
return
else:
rect.append(mid[:])
return
trackback(n,0)
for i in range(0,n):
print(rect[0][i],end=" ")
5.kAc给糖果你吃
问题描述:kAc有n堆糖果,每堆有A[i]个。kAc说你只能拿m次糖果,聪明的你当然想要拿最多的糖果来吃啦啦啦~//第二天,kAc问你还想吃糖果么?(嘿嘿嘿)说着眼角路出奇怪的微笑...
'''
输入格式
第一行两个数字n和m,第二行有n个数字A[i]。
输出格式
输出一行表示最多能拿几个糖果。
样例输入
2 2
1 2
样例输出
3
'''
n ,m = map(int,input().split())
A = list(map(int,input().split()))
result = 0
#利用循环每次找到最大的一个,然后移除
#利用贪心,每次都找到局部最大的,再到总体最大
for i in range(m):
mid= max(A)
result += mid
A.remove(mid)
print(result)
6.无聊的逗
问题描述:逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中。不过他想到了一个游戏来使他更无聊。他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的情况下长度最长是多少。
思路:
- 我的思路是动态规划寻找等和子集,这道题其实就可以理解为寻找等和子集,如果不能找到,那就删除一个数再寻找
- 我的代码是先查找所给出的数组能否找到一个等和子集
- 然后再每次删除数组中的一个数然后再寻找是否能找到等和子集
- 将所有情况都记录下来,最终输出最大的等和子集
'''
输入格式
第一行一个数n,表示n个棍子。第二行n个数,每个数表示一根棍子的长度。
输出格式
一个数,最大的长度。
样例输入
4
1 2 3 1
样例输出
3
'''
n = int(input())
N = list(map(int,input().split()))
#动态规划寻找等和子集的和函数
def find_all(nums):
n = len(nums)
if n < 2:
return
total = sum(nums)
maxNum = max(nums)
if total & 1:
return
target = total // 2
if maxNum > target:
return
dp = [[False] * (target + 1) for _ in range(n)]
for i in range(n):
dp[i][0] = True
dp[0][nums[0]] = True
for i in range(1, n):
num = nums[i]
for j in range(num, target + 1):
if j >= num:
dp[i][j] = dp[i - 1][j] | dp[i - 1][j - num]
else:
dp[i][j] = dp[i - 1][j]
if dp[n - 1][target] == True:
return target
#找到等和函数中最大的数
def maxnum(n,N):
result = []
#这一步先找给出的数列中可不可以直接分为等和函数
a = find_all(N)
if a != None:
result.append(a)
#依次减去每一个数后查看是否能找到等和子集
for i in range(n):
mid = N[0:i] + N[i+1:n]
a = find_all(mid)
if a != None:
result.append(a)
#输出等和子集中最大的一个
print(max(result))
maxnum(n,N)
7.跳马
问题描述:一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
思路:DFS
'''
输入格式
一行四个数字a,b,c,d。
输出格式
如果跳不到,输出-1;否则输出最少跳到的步数。
样例输入
1 1 2 3
样例输出
1
'''
a,b,c,d = map(int,input().split())
#因为马走'日'字,所以可以跳8个方向,一次列出来
hourse = [[2,1],[2,-1],[1,-2],[-1,-2],[-2,-1],[-2,1],[-1,2],[1,2]]
#记录最小步数
min_step = float("inf")
#创建一个棋盘,为什么是9X9呢,因为可以与坐标对应且记录是否已经走过
visited = [[0 for _ in range(9)] for _ in range(9)]
#开始定义DFS函数
def DFS(x,y,step):
global min_step,visited
#此处剪枝操作,只要比记录过的最小步数大的就不再遍历,减少搜索次数
if step > min_step:
return
#终止条件,只要到了预期的坐标就结束
if x ==c and y ==d:
min_step = step
return
#分别便利hourse里面的8个坐标,搜索每一个都可以到的位置
for i in range(8):
x_new = x + hourse[i][0]
y_new = y + hourse[i][1]
if x_new > 0 and x_new <= 8 and y_new > 0 and y_new <= 8:
#记录走过的地方,不重复
if visited[x_new][y_new] == 0:
visited[x_new][y_new] = 1
DFS(x_new,y_new,step+1)
visited[x_new][y_new] = 0
#初始化(a,b)为已访问
visited[a][b] = 1
DFS(a,b,0)
#如果没有返回步数则走不到,返回-1
if min_step == float("inf"):
print(-1)
else:
print(min_step)
8.最大分解
问题描述:给出一个正整数n,求一个和最大的序列a0,a1,a2,……,ap,满足n=a0>a1>a2>……>ap且ai+1是ai的约数,输出a1+a2+……+ap的最大值
思路:贪心+递归
'''
输入格式
输入仅一行,包含一个正整数n
输出格式
一个正整数,表示最大的序列和,即a1+a2+……+ap的最大值
样例输入
10
样例输出
6
'''
n = int(input())
nums = []
flag = 0
def digui(n):
#设置一个标志位,当最后一个数到1时就开始不再搜索
global flag
begin = n-1
while begin > 0:
if flag == 1:
return
# 约数就是后一个数能不能被前一个数整除
if n % begin == 0:
if begin == 1:
flag = 1
nums.append(begin)
#现在就以ai为开头继续往下搜索
digui(begin)
begin -= 1
digui(n)
result = 0
for i in range(len(nums)):
result += nums[i]
print(result)
9.粘木棍
问题描述:有N根木棍,需要将其粘贴成M个长木棍,使得最长的和最短的的差距最小。
思路:DFS
'''
输入格式
第一行两个整数N,M。
一行N个整数,表示木棍的长度。
输出格式
一行一个整数,表示最小的差距
样例输入
3 2
10 20 40
样例输出
10
'''
n,m = map(int,input().split())
nums = list(map(int,input().split()))
double = [0 for _ in range(m)]
seen = []
target = float("inf")
def DFS(flag): #flag记录已经算过多少个数,target最小值
global target
if flag == n:
if m != 1 and 0 in double:
return
if max(double)-min(double) > target:
return
target = max(double)-min(double)
return
for i in range(m):
for j in nums:
if j in seen:
None
else:
seen.append(j)
double[i] += j
DFS(flag+1)
seen.pop()
double[i] -= j
DFS(0)
print(target)
10.数的潜能
问题描述:将一个数N分为多个正整数之和,即N=a1+a2+a3+…+ak,定义M=a1*a2*a3*…*ak为N的潜能。给定N,求它的潜能M。由于M可能过大,只需求M对5218取模的余数。
思路:两张方法:DFS和数学归纳法
'''
输入格式
输入共一行,为一个正整数N。
输出格式
输出共一行,为N的潜能M对5218取模的余数。
样例输入
10
样例输出
36
'''
'''递归'''
'''
n = int(input())
result = 0
mid = []
def DFS(nums):
global result,mid
if nums > n:
return
if nums == n:
mid_result = 1
for i in range(len(mid)):
mid_result = mid_result * mid[i]
if mid_result >= result:
result = mid_result
return
for j in range(2):
nums += j+2
mid.append(j+2)
DFS(nums)
nums -= j+2
mid.pop()
if n == 1:
print(1)
else:
DFS(0)
print(result)
'''
'''归纳'''
'''
n = int(input())
f = 3
if n==1:
print(1)
elif n==2:
print(2)
elif n==3:
print(3)
else:
for i in range(4,n+1):
if (i-1)%3 == 0:
f = f//3*4
else:
f = f//2*3
print(f%5218)
'''
自己写的所以有点复杂,但是至少能完成嘿嘿。如果各位有优化欢迎评论区讨论!!
大功告成!编写不易,大家成功后点个关注or赞谢谢~~
蓝桥杯练习系统—算法训练 s01串
第一部分:题目
按以下方式变换
0变1,1变01
第二部分:思路
循环+中间数组。有一点小小的技巧就是,0->1,1->01.就是都变成1,只不过原先是1的话在前面加一个0.
第三部分:代码
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; char s[20000]; int slen; void changing() { char t[20000]; int len=0; for(int i=0;i<slen;i++) { if(s[i]==\'1\') { t[len++]=\'0\'; } t[len++]=\'1\'; } for(int i=0;i<len;i++) { s[i]=t[i]; } slen=len; } int main() { int n; s[0]=\'0\'; slen=1; cin>>n; while(n--) { changing(); } cout<<s<<endl; return 0; }
以上是关于[蓝桥杯Python]算法练习算法基础算法训练算法模板(持续更新)的主要内容,如果未能解决你的问题,请参考以下文章