【思特奇杯·云上蓝桥-算法集训营】第二周

1.带分数

from itertools import permutations

num = int(input())
ans = 0
for n in range(1, num + 1):
    if '0' in str(n) or len(set(list(str(n)))) != len(str(n)):
        # 判断是否有0和重复数字
        continue

    diff = num - n  # 剩下的数(后面的分数应该算出来的值)
    s = '123456789'
    for i in str(n):
        s = s.replace(i, '')  # 去掉已经使用过的数

    for length in range(1, len(s) // 2 + 1):  # 分母的长度
        for i in permutations(s, length):  # 长度为length的分母的全排列
            fenzi = str(int(''.join(i)) * diff)  # 计算分子
            if len(fenzi) == len(s) - length:  # 判断计算出来的分子是否合法
                if set(list(fenzi)) == set(list(s)) - set(list(''.join(i))):
                    ans += 1

print(ans)

2.李白打酒

def dfs(a, b, c): # 遇到店的剩余次数,遇到花的剩余次数,剩余酒的数量
    ans = 0
    if a == 0 and b == 0 and c == 1:
        return 1
    if a > 0:
        ans += dfs(a - 1, b, c * 2) # 遇到店
    if b > 0:
        ans += dfs(a, b - 1, c - 1) # 遇到花
    return ans

print(dfs(5, 9, 2))


num = 0
def dfs(a, b, c):
    if a == 0 and b == 0 and c == 1:
        global num
        num += 1
        return
    if a > 0:
        dfs(a-1, b, c*2)
    if b > 0:
        dfs(a, b-1, c-1)
    

dfs(5, 9, 2)
print(num)

3.第39级台阶

lis = [[-1] * 39 for _ in range(39)]

def dfs(n, s):  # n代表阶梯数,s代表步数
    if n > 39:
        return 0
    elif n == 39:
        return 1 if s % 2 == 0 else 0

    if lis[n][s] != -1:
        return lis[n][s]
    else:
        ans = dfs(n + 1, s + 1) + dfs(n + 2, s + 1)
        lis[n][s] = ans
        return ans

print(dfs(0, 0))

4.穿越雷区

n = int(input())

m = [input().split(' ') for _ in range(n)]

visit = [[False] * n for _ in range(n)] # 记录是否访问过

step = [(0, -1), (0, 1), (-1, 0), (1, 0)]

queue = [(0, 0, 0)] # 存三个值:坐标、当前移动的步数

while queue:
    y, x, t = queue.pop(0)
    if m[y][x] == 'B':
        print(t)
        break
    for dy, dx in step:
        ny = y + dy
        nx = x + dx
        if -1 < nx < n and -1 < ny < n:
            if not visit[ny][nx] and m[y][x] != m[ny][nx]:
            	# 没有访问过并且不是连续走相同的区域
                queue.append((ny, nx, t+1))
                visit[y][x] = True
    
if not queue:
    print(-1)

5.迷宫

m = '''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'''

m = m.split('\n')

visit = [[False] * 50 for _ in range(30)]
visit[0][0] = True

step = [(1, 0, 'D'), (0, -1, 'L'), (0, 1, 'R'), (-1, 0, 'U')]


queue = [(0, 0, -1, 0)] # 坐标、父节点在path中的下标、走的方向对应的字母
path = []
while queue:
    y, x, _, _  = cur = queue.pop(0)
    path.append(cur)

    if cur[:2] == (29, 49):
        # 走到终点
        temp = []
        i = len(path) - 1
        while i > 0: # 沿着之前标记的父节点将路径取出
            temp.append(path[i][3])
            i = path[i][2]
        temp.reverse() # 反转,因为取出来的路径是反的
        print(''.join(temp))
        break

    for dy, dx, dir in step: # 往上下左右走一步
        ny, nx = y+dy, x+dx # 下一步到达的位置
        if -1 < nx < 50  and -1 < ny < 30 and m[ny][nx] == '0' and not visit[ny][nx]:
            # 判断是否越界、迷宫该位置是否能走、是否已经走过
            queue.append((ny, nx, len(path)-1, dir)) # 将下一步添加到队列中,len(path)-1 是添加到节点的父节点在path中的下标
            visit[ny][nx] = True # 标记已经访问过

6.跳马

a, b, c, d = map(int, input().split(' '))

step = [(1, 2), (1, -2), (-1, 2), (-1, -2), (2, 1), (2, -1), (-2, 1), (-2, -1)]

visit = [[False]*8 for _ in range(8)]


queue = [(a, b, 0)] # 坐标、步数

while queue:
    y, x, t = queue.pop(0)

    if y == c and x == d:
        print(t)
        break

    for dy, dx in step:
        ny = y + dy
        nx = x + dx
        if -1 < ny < 8 and -1 < nx < 8 and not visit[ny][nx]:
            queue.append((ny, nx, t+1))
            visit[ny][nx] = True
    
if not queue:
    print(-1)

7.路径之谜

n = int(input())

nums = [list(map(int, input().split(' '))) for _ in range(2)] # 第一行是上面的,第二行是左面的

visit = [[False]*n for _ in range(n)]
visit[0][0] = True

ans = [0]

record = [[0]*n for _ in range(2)]
record[0][0] = record[1][0] = 1

step = [(0, -1), (0, 1), (-1, 0), (1, 0)]

def dfs(y, x):
    if y == n-1 and x == n-1 and record == nums:
        print(' '.join(map(str, ans)))
        return
    for dy, dx in step:
        ny = y + dy
        nx = x + dx
        if -1 < ny < n and -1 < nx < n and not visit[ny][nx]:
            ans.append(ny*n + nx)
            visit[ny][nx] = True
            record[0][nx] += 1
            record[1][ny] += 1

            dfs(ny, nx)

            ans.pop()
            visit[ny][nx] = False
            record[0][nx] -= 1
            record[1][ny] -= 1
            
dfs(0, 0)

8.未名湖边的烦恼

m, n = map(int, input().split(' '))

record = [[-1]*(n+1) for _ in range(m+1)]

def dfs(a, b): # 还鞋、借鞋
    if a == b == 0:
        return 1
    
    if record[a][b] != -1:
        ans = record[a][b]
    else:
        ans = 0
        if a > 0:
            ans += dfs(a-1, b)
        if 0 < b <= a:
            ans += dfs(a, b-1)
        record[a][b] = ans
    
    return ans

print(dfs(m, n))

9.大臣的旅费

cnt=0
node=0
def dfs(v,k):   #进行dfs搜索
    global cnt
    global node
    global vis
    if k>cnt:
        cnt=k
        node=v
    for i in range(len(E[v])):
        if vis[E[v][i][0]]==False: #没访问过的点都进行一次dfs
            vis[E[v][i][0]]=True #进行标记
            dfs(E[v][i][0],k+E[v][i][1])
            vis[E[v][i][0]]=False #回溯
n=int(input())
E=[[]for i in range(n+1)]
vis=[False for i in range(n+1)]
for i in range(n-1):
    x,y,z=map(int,input().split())
    E[x].append((y,z))
    E[y].append((x,z)) #将各个点进行连接,用列表数组的方式进行
vis[1]=True
dfs(1,0)  #找到距离1最远的点node
vis[1]=False
cnt=0
vis[node]=True
dfs(node,0)  #从node出发,找到最远的点,就是所要求的最远距离
res=0
for i in range(1,cnt+1):
    res+=i+10
print(res)

10.2n皇后问题

def conflict(queen_lis, new_queen):
    """判断棋子是否符合规则"""
    for index, queen in enumerate(queen_tup):
        if abs(new_queen - queen) in (len(queen_tup) - index, 0):  # 判断表达式:垂直距离和水平距离
            # 列数之差是否等于行数之差,或者列数之差为零
            # 注意,len(queen_tup)是行数。因为第一行不进入循环,所以,这里的行数要比len出来的值加一,也就是,len(queen_tup)如果等于3,那么对应的是第四行
            # 对应的,index也是要加一的。
            return False
    return True


def arrange_queen(num, queen_lis=[]):
    """
    :param num:棋盘的的行数,当然数值也等于棋盘的列数
    :param queen_tup: 设置一个空队列,用于保存符合规则的棋子的信息
    """
    for new_queen in range(num):  # 遍历一行棋子的每一列

        if conflict(queen_tup, new_queen):  # 判断是否冲突

            if len(queen_tup) == num - 1:  # 判断是否是最后一行
                yield [new_queen]  # yield关键字,返回当前的位置。

            else:
                # 若果不是最后一行,递归函数接着放置棋子

                for result in arrange_queen(num, queen_lis + [new_queen]):# 结果的迭代
                    yield [new_queen] + result # 这个是每个函数最终的地方。


for i in arrange_queen(4):
    print(i)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cooolting

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值