自学内容网 自学内容网

蓝桥杯Learning

Part 1 递归和递推

1. 简单斐波那契数列

n = int(input())

st = [0]*(47) # 注意这个地方,需要将数组空间设置的大一些,否则会数组越界
st[1] = 0
st[2] = 1
# 这个方法相当于是递推,即先求解一个大问题的若干个小问题
def dfs(u):
    if u ==1:
        print(st[1],end=" ")
    if u ==2:
        print(str(st[1])+" "+str(st[2]),end=" ") # 注意在这个地方,在acwing当中需要进行强制类型转换
    if u>2 :
        for i in range (3,u+1):
            st[i] =st[i-1]+st[i-2]
        for i in range (1,u+1):
            print(st[i],end=" ")
    return
dfs(n)

# 方法2 采用递归的方法,递归可以看做将一个大问题分解为若干个小问题,进行求解
def fibonacci(n):
    if n == 1:
        return 0
    elif n == 2:
        return 1
    else:
        fib_list = [0, 1] # 注意这个地方,python列表的下标从0开始
        for i in range(2, n):
            fib_list.append(fib_list[i-1] + fib_list[i-2])
        return fib_list[-1]

n = int(input())
# 输出斐波那契数列的前 n 个数字
for i in range(1,n+1):
    print(fibonacci(i), end=' ')

2. 递归实现指数型枚举

# 指数枚举相当于每一个位置的数字可以选择或者不选
n = int(input())

st = [0] * (n+1) #python当中的下标是从0开始的。该数组用于保存每个位置数字的选择情况。0表示无判断,2表示不选,1表示选

def dfs(u):
    if u > n:
        for i in range(1, n + 1):
            if st[i] == 1:
                print(i, end=' ')
        print()
        return #注意,这里需要一个return

    st[u] = 2
    dfs(u + 1)      # 第一个分支:不选
    st[u] = 0       # 恢复现场

    st[u] = 1
    dfs(u + 1)      # 第二个分支:选
    st[u] = 0

dfs(1)

3. 递归实现排列型枚举

# 顺序1 依次枚举每个数放到哪个位置
# 顺序2 依次枚举每个位置放哪个数

# 相当于是在求解一个全排列问题
# 排列问题当中需要一个判断是否重复的数组

# 方法1:
n = int(input())
st = [0]*(n+1) # 表示当前的状态,0表示还没放数,1-n表示放了哪一个数
used =[False]*(n+1) # 表示某个数是否被用过, true表示已经用过

def dfs(u):
    if u>n: #边界
        for i in range (1,n+1):
            print(st[i],end=' ') #打印每一个方案
        print()
        return #注意这个return的位置
    # 依次枚举每个分支,即当前位置可以填哪些数
    for i in range (1,n+1):
        if used[i] ==False:
            st[u] =i
            used[i] =True
            dfs(u+1) # 注意每次递归运行到这里的时候现场还没有恢复
            #恢复现场
            st[u] =0
            used[i] = False

dfs(1)

4.递归实现组合型枚举

n,m = map(int,input().split())
st = [0]*30

def dfs(u,s): # u表示从第几个位置开始枚举,第二个位置表示当前从哪一个数开始
    if u ==m+1: #边界,表示已经选了m个数
        for i in range (1,m+1):
            print(st[i],end=' ')
        print()
        return
    for i in range(s,n+1):
        st[u] =i
        dfs(u+1,i+1) # 注意这个地方,u相当于是指示当前是枚举第几个位置,i相当数是指示当前位置开始可以选择的最小的数

        st[u] =0 # 恢复现场

dfs(1,1)

方法2:

n,m = map(int,input().split())
st = [0]*30

def dfs(u,s): # u表示从第几个位置开始枚举,第二个位置表示当前从哪一个数开始
    if u+n-s < m: # 剪枝,相当于想后面所有数都选上都不够m个,则无解
        return
    if u ==m+1: #边界,表示已经选了m个数
        for i in range (1,m+1):
            print(st[i],end=' ')
        print()
        return
    for i in range(s,n+1):
        st[u] =i
        dfs(u+1,i+1) # 注意这个地方,u相当于是指示当前是枚举第几个位置,i相当数是指示当前位置开始可以选择的最小的数

        st[u] =0 # 恢复现场

dfs(1,1)

5. 带分数问题

n = int(input())
st = [False] * 10
backup = [False] * 10

ans = 0


def check(a, c):
    b = n * c - a * c
    if not a or not b or not c:  # a,b,c 都不可以等于0
        return False

    backup =st[:] # python当中的切片操作

    while b: # 此处需要注意将一个数各个位上的数字取出来的方法
        x = b % 10  # 取个位 先去取个位上的数字
        b //= 10  # 个位删掉
        if not x or backup[x]: # 需要去判断x是否为0,以及这个数是否被用过
            return False
        backup[x] = True

    for i in range(1, 10): # 这个 for循环相当于去判断1-9是否都已经使用过
        if not backup[i]:
            return False

    return True


def dfs_c(u, a, c):
    global ans
    if u == n:
        return
    if check(a, c) == True:
        ans += 1
    for i in range(1, 10):  # 这部分相当于是去选c
        if st[i] == False:
            st[i] = True
            dfs_c(u + 1, a, c * 10 + i) # 注意这里再一个数字后加上一位的方法
            st[i] = False


def dfs_a(u, a):  # u相当于是当前用了几个数字,a相当于当前位置a放置的数
    if (a >= n):  # 当a>n的时候,这种情况直接舍去
        return
    dfs_c(u, a, 0)  # 相当于在a的递归搜索数的叶子节点,再依次遍历 c

    for i in range(1, 10):  # 这部分相当于去选a,即全排列位置a上的数字
        if st[i] == False:
            st[i] = True
            dfs_a(u + 1, a * 10 + i)
            st[i] = False


dfs_a(0, 0)
print(ans)


原文地址:https://blog.csdn.net/weixin_45951642/article/details/136307903

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!