137 lines
5.2 KiB
Python
137 lines
5.2 KiB
Python
# -*-coding: GBK -*-
|
||
import heapq # 导入堆模块,用于实现优先队列
|
||
from typing import List, Optional, Tuple # 导入类型提示相关模块
|
||
|
||
|
||
def boss_strategy(coin: int, blood: int) -> Optional[Tuple[List[str], int]]:
|
||
# 使用分支限界法寻找最小回合数击败BOSS的技能序列
|
||
|
||
# 参数:
|
||
# coin: 玩家初始金币数
|
||
# blood: BOSS初始血量
|
||
|
||
# 返回:
|
||
# 最小回合数的技能序列列表,如果无解则返回None
|
||
|
||
start_coin = coin # 记录初始金币数,用于计算消耗金币
|
||
|
||
# 初始状态: (回合数, 剩余金币, BOSS血量, 充能, 连续E计数, 技能序列元组)
|
||
start_state = (0, coin, blood, 0, 0, ())
|
||
|
||
# 创建优先队列: 元素为 (优先级, 状态)
|
||
# 优先级元组: (回合数, 消耗金币, BOSS血量) - 值越小优先级越高
|
||
heap = []
|
||
heapq.heappush(heap, ((0, 0, blood), start_state)) # 将初始状态加入优先队列
|
||
|
||
# 创建访问集合: 用于避免重复状态
|
||
# 状态键: (回合数, 剩余金币, BOSS血量, 充能, min(连续E计数,3))
|
||
visited = set()
|
||
start_ce_compressed = min(0, 3) # 压缩连续E计数状态
|
||
visited.add((0, coin, blood, 0, start_ce_compressed)) # 将初始状态加入已访问集合
|
||
|
||
# 设置最大回合数限制,避免无限循环
|
||
max_round = blood * 2 # 每次至少造成1点伤害,最多回合数为血量两倍
|
||
|
||
# 主循环: 处理优先队列中的状态
|
||
while heap:
|
||
# 从优先队列中取出优先级最高的状态
|
||
priority, state = heapq.heappop(heap)
|
||
# 解包状态元组
|
||
round_cnt, cur_coin, cur_blood, energy, ce, seq_tuple = state
|
||
|
||
# 检查是否已击败BOSS
|
||
if cur_blood <= 0:
|
||
return (list(seq_tuple), cur_coin) # 返回技能序列和剩余金币
|
||
|
||
# 超过最大回合数则跳过当前状态
|
||
if round_cnt >= max_round:
|
||
continue
|
||
|
||
# 尝试使用技能A
|
||
if cur_coin >= 2: # 检查金币是否足够
|
||
new_coin = cur_coin - 2 # 扣除金币
|
||
new_blood = cur_blood - 1 # 减少BOSS血量
|
||
new_energy = energy + 1 # 增加充能
|
||
new_ce = 0 # 使用非E技能,重置连续E计数
|
||
new_round = round_cnt + 1 # 回合数+1
|
||
new_seq = seq_tuple + ('A',) # 添加技能到序列
|
||
|
||
# 压缩连续E计数状态(>=3视为3)
|
||
ce_compressed = min(new_ce, 3)
|
||
# 创建状态键用于去重
|
||
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
|
||
|
||
# 检查是否为新状态
|
||
if state_key not in visited:
|
||
visited.add(state_key) # 标记为已访问
|
||
cost = start_coin - new_coin # 计算已消耗金币
|
||
# 创建新状态
|
||
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
|
||
# 将新状态加入优先队列
|
||
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
|
||
|
||
# 尝试使用技能E
|
||
cost_e = 3 # 默认消耗金币
|
||
if ce >= 2: # 检查是否为连续第三次使用E
|
||
cost_e = 2 # 第三次消耗2金币
|
||
|
||
if cur_coin >= cost_e: # 检查金币是否足够
|
||
new_coin = cur_coin - cost_e # 扣除金币
|
||
new_blood = cur_blood - 3 # 减少BOSS血量
|
||
new_energy = energy + 1 # 增加充能
|
||
new_ce = ce + 1 # 增加连续E计数
|
||
new_round = round_cnt + 1 # 回合数+1
|
||
new_seq = seq_tuple + ('E',) # 添加技能到序列
|
||
|
||
# 压缩连续E计数状态
|
||
ce_compressed = min(new_ce, 3)
|
||
# 创建状态键用于去重
|
||
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
|
||
|
||
# 检查是否为新状态
|
||
if state_key not in visited:
|
||
visited.add(state_key) # 标记为已访问
|
||
cost = start_coin - new_coin # 计算已消耗金币
|
||
# 创建新状态
|
||
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
|
||
# 将新状态加入优先队列
|
||
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
|
||
|
||
# 尝试使用技能Q
|
||
if energy >= 3 and cur_coin >= 3: # 检查充能和金币是否足够
|
||
new_coin = cur_coin - 3 # 扣除金币
|
||
new_blood = cur_blood - 8 # 减少BOSS血量
|
||
new_energy = energy - 3 # 消耗充能
|
||
new_ce = 0 # 使用非E技能,重置连续E计数
|
||
new_round = round_cnt + 1 # 回合数+1
|
||
new_seq = seq_tuple + ('Q',) # 添加技能到序列
|
||
|
||
# 压缩连续E计数状态
|
||
ce_compressed = min(new_ce, 3)
|
||
# 创建状态键用于去重
|
||
state_key = (new_round, new_coin, new_blood, new_energy, ce_compressed)
|
||
|
||
# 检查是否为新状态
|
||
if state_key not in visited:
|
||
visited.add(state_key) # 标记为已访问
|
||
cost = start_coin - new_coin # 计算已消耗金币
|
||
# 创建新状态
|
||
new_state = (new_round, new_coin, new_blood, new_energy, new_ce, new_seq)
|
||
# 将新状态加入优先队列
|
||
heapq.heappush(heap, ((new_round, cost, new_blood), new_state))
|
||
|
||
return None # 队列为空,无解
|
||
|
||
|
||
# 主程序入口
|
||
if __name__ == "__main__":
|
||
# 测试示例: 金币=10, BOSS血量=10
|
||
result = boss_strategy(20, 20)
|
||
|
||
if result is None:
|
||
print("无法击败BOSS")
|
||
else:
|
||
skill_sequence, remaining_coins = result
|
||
print("最小回合数技能序列:", skill_sequence) # 预期输出: ['A', 'A', 'A', 'Q']
|
||
print("剩余金币:", remaining_coins) # 预期输出: 1
|