从0开始学算法——第十八天(分治算法练习)

写在开头的话

学习了今天的基础知识,让我们来做几道题来练练手吧。(题目是别的地方扒来的,参考答案是我自己写的,肯定不是最优解,有更好的方法欢迎评论区交流)

题目一------汉诺塔

题目二------情景题

题目三------蛋糕美味值

参考答案

第一题参考答案(Python版)

python 复制代码
def hanoi_tower(n, m, source, target, auxiliary, step_count, current_step):
    """
    n: 当前要移动的盘子数量
    m: 目标步数
    source: 源柱子
    target: 目标柱子
    auxiliary: 辅助柱子
    step_count: 当前已移动步数
    current_step: 当前步数的引用列表(用于记录当前步数)
    """
    if n == 0:
        return step_count
    
    # 移动n-1个盘子从source到auxiliary
    step_count = hanoi_tower(n-1, m, source, auxiliary, target, step_count, current_step)
    
    # 如果已经找到目标步数,直接返回
    if current_step[0] is not None:
        return step_count
    
    # 移动第n个盘子
    step_count += 1
    if step_count == m:
        current_step[0] = f"#{n}: {source}->{target}"
        return step_count
    
    # 移动n-1个盘子从auxiliary到target
    step_count = hanoi_tower(n-1, m, auxiliary, target, source, step_count, current_step)
    
    return step_count

def main():
    # 读取输入
    N, M = map(int, input().split())
    
    # 计算最少移动步数
    min_steps = 2**N - 1
    
    # 查找第M步的移动
    current_step = [None]
    total_steps = hanoi_tower(N, M, 'A', 'C', 'B', 0, current_step)
    
    # 输出结果
    if current_step[0]:
        print(current_step[0])
    else:
        print("#Invalid step")
    
    print(min_steps)

if __name__ == "__main__":
    main()

第二题参考答案(Python版)

python 复制代码
import sys
from functools import lru_cache

MOD = 998244353

def modinv(x: int) -> int:
    """返回x在模MOD下的逆元,MOD为质数"""
    return pow(x, MOD - 2, MOD)

def solve() -> None:
    data = sys.stdin.read().strip().split()
    if not data:
        return
    it = iter(data)
    n = int(next(it))
    k = int(next(it)) - 1          # 转为0-indexed
    a = [int(next(it)) for _ in range(n)]

    damages = [5, 4, 3, 2, 1]      # 依次造成的伤害值

    @lru_cache(maxsize=None)
    def dfs(i: int, state: tuple) -> int:
        """
        返回:从当前状态继续,最终第k个随从死亡的概率(模MOD)
        i: 已经完成了i次伤害 (0 <= i <= 5)
        state: 长度为n的元组,表示每个随从的当前血量(死亡则为0)
        """
        if i == 5:                 # 所有伤害完成
            return 1 if state[k] <= 0 else 0

        # 找出所有存活随从的索引
        alive = [idx for idx in range(n) if state[idx] > 0]
        if not alive:              # 没有存活随从,法术终止
            return 1 if state[k] <= 0 else 0

        d = damages[i]             # 本次伤害值
        m = len(alive)
        inv_m = modinv(m)          # 存活数的逆元
        res = 0
        for idx in alive:
            new_state = list(state)
            new_hp = state[idx] - d
            if new_hp < 0:
                new_hp = 0
            new_state[idx] = new_hp
            res = (res + dfs(i + 1, tuple(new_state))) % MOD
        res = res * inv_m % MOD
        return res

    ans = dfs(0, tuple(a))
    print(ans)

if __name__ == "__main__":
    solve()

第三题参考答案(Python版)

python 复制代码
def max_taste_sum():
    import sys
    
    # 读取输入
    data = sys.stdin.read().strip().split()
    n, k = map(int, data[:2])
    tastes = list(map(int, data[2:]))
    
    max_sum = 0
    
    # 使用位运算枚举所有子集
    for mask in range(1 << n):  # 枚举0到2^n-1
        current_sum = 0
        # 检查mask的每一位,如果为1则选择对应蛋糕
        for i in range(n):
            if mask & (1 << i):
                current_sum += tastes[i]
        
        # 如果当前和小于k且大于已知最大值,则更新
        if current_sum < k and current_sum > max_sum:
            max_sum = current_sum
    
    print(max_sum)

if __name__ == "__main__":
    max_taste_sum()
相关推荐
月明长歌2 小时前
【码道初阶】【LeetCode 958】判定完全二叉树:警惕 BFS 中的“管中窥豹”陷阱
算法·leetcode·宽度优先
蓝桉~MLGT3 小时前
Ai-Agent学习历程—— Agent认知框架
人工智能·学习
لا معنى له3 小时前
学习笔记:卷积神经网络(CNN)
人工智能·笔记·深度学习·神经网络·学习·cnn
蒙奇D索大3 小时前
【数据结构】考研408 | 冲突解决精讲: 拉链法——链式存储的艺术与优化
数据结构·笔记·考研·改行学it
一直都在5723 小时前
数据结构入门:二叉排序树的构建与相关算法
数据结构·算法
_Minato_3 小时前
数据结构知识整理——复杂度的计算
数据结构·经验分享·笔记·算法·软考
listhi5203 小时前
针对燃油运输和车辆调度问题的蚁群算法MATLAB实现
前端·算法·matlab
x_lrong3 小时前
交叉验证笔记
笔记
月明长歌3 小时前
【码道初阶】【LeetCode 102】二叉树层序遍历:如何利用队列实现“一层一层切蛋糕”?
java·数据结构·算法·leetcode·职场和发展·队列