从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()
相关推荐
ZC跨境爬虫8 分钟前
LeetCode 88. 合并两个有序数组(双指针详解 + Java Python 实现)
java·python·算法·leetcode
Nil20811 分钟前
leetcode 238除了自身以外数组的乘积
数据结构·算法·leetcode
土司大王11 分钟前
LeetCode hot100——最长连续序列
数据结构·算法·leetcode
caimouse12 分钟前
ReactOS 图形系统分析(17):区域填充 — EngPaint / IntEngPaint(paint.c)
c语言·开发语言·算法
生态学者16 分钟前
Ecological Indicators | 机场鸟调的新方法:用 AWM-PC1 读懂干扰梯度下的鸟类群落
人工智能·算法·r语言·微信公众平台
Herbert_hwt24 分钟前
第六章 Java深入理解接口、函数式接口与lambda表达式
java·开发语言·算法
橙橙笔记43 分钟前
C++的学习第三部分
开发语言·c++·学习
君君思密达1 小时前
LeetCode Hot 100 题目详解-滑动窗口
算法·leetcode·职场和发展
GreenTea9 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
bitbrowser9 小时前
giffgaff突然停用?先分清闲置停用和长期境外断开
笔记