# -*- coding: utf-8 -*- import math import heapq def boss_fight(B, PlayerSkills): """ 使用分支限界法求解Boss战斗的最优策略 参数: B: Boss血量序列 [boss1_hp, boss2_hp, ...] PlayerSkills: 玩家技能列表 [(damage1, cooldown1), (damage2, cooldown2), ...] 返回: 每个Boss对应的攻击序列列表,例如:[[0, 1, 0], [2, -1, 1], ...] 其中数字表示技能索引,-1表示等待 如果无解则返回None """ n = len(B) # Boss数量 m = len(PlayerSkills) # 技能数量 if n == 0: return [] # 计算最大平均伤害(用于启发式估计) max_avg = 0.0 for damage, cooldown in PlayerSkills: if cooldown + 1 > 0: avg_damage = damage / (cooldown + 1) if avg_damage > max_avg: max_avg = avg_damage # 如果所有技能伤害为0,则无法击败Boss if max_avg == 0: return None # 初始状态:Boss索引0,血量B[0],所有技能冷却为0,回合数0 start_cooldown = tuple([0] * m) total_remaining = sum(B) # 启发式函数:当前回合数 + 估计剩余回合数 f_value = math.ceil(total_remaining / max_avg) if max_avg > 0 else total_remaining # 初始化优先队列 (f_value, round_count, boss_idx, boss_remaining_hp, cooldown_tuple, boss_paths) # boss_paths是一个列表,每个元素是对应Boss的攻击序列 initial_boss_paths = [[] for _ in range(n)] queue = [(f_value, 0, 0, B[0], start_cooldown, initial_boss_paths)] # 记录访问过的状态 (boss_idx, boss_remaining_hp, cooldown_tuple) -> 最小回合数 visited = {} visited[(0, B[0], start_cooldown)] = 0 # A*搜索主循环 while queue: # 弹出f_value最小的状态进行扩展 f_value, round_count, boss_idx, boss_rem, cooldown, boss_paths = heapq.heappop(queue) state_key = (boss_idx, boss_rem, cooldown) # 状态剪枝:如果已有更好的状态到达当前状态,跳过 if visited.get(state_key, float('inf')) < round_count: continue # 目标状态:所有Boss都被击败 if boss_idx >= n: return boss_paths # 动作1:等待(所有技能冷却时间-1,回合数+1) new_cooldown_list = [max(0, c - 1) for c in cooldown] new_cooldown = tuple(new_cooldown_list) new_round = round_count + 1 new_state_key = (boss_idx, boss_rem, new_cooldown) # 如果这个等待状态更优,则加入队列 if new_state_key not in visited or visited[new_state_key] > new_round: visited[new_state_key] = new_round # 重新计算启发式值 total_remaining = boss_rem + sum(B[boss_idx+1:]) estimate_rounds = math.ceil(total_remaining / max_avg) if max_avg > 0 else 0 new_f = new_round + estimate_rounds # 复制boss_paths并给当前Boss添加等待动作 new_boss_paths = [path[:] for path in boss_paths] new_boss_paths[boss_idx].append(-1) # -1表示等待 heapq.heappush(queue, (new_f, new_round, boss_idx, boss_rem, new_cooldown, new_boss_paths)) # 动作2:使用技能 for skill_idx, (damage, skill_cooldown) in enumerate(PlayerSkills): # 检查技能是否可用(冷却时间为0) if cooldown[skill_idx] != 0: continue new_boss_idx = boss_idx new_boss_rem = boss_rem - damage # 复制boss_paths并给当前Boss添加技能使用 new_boss_paths = [path[:] for path in boss_paths] new_boss_paths[boss_idx].append(skill_idx) # 检查是否击败了当前Boss if new_boss_rem <= 0: new_boss_idx += 1 if new_boss_idx < n: new_boss_rem = B[new_boss_idx] # 切换到下一个Boss else: new_boss_rem = 0 # 所有Boss都被击败 # 更新技能冷却时间 new_cooldown_list = [max(0, c - 1) for c in cooldown] new_cooldown_list[skill_idx] = skill_cooldown # 设置使用技能的冷却时间 new_cooldown = tuple(new_cooldown_list) new_round = round_count + 1 # 如果所有Boss都被击败,直接返回结果 if new_boss_idx >= n: return new_boss_paths new_state_key = (new_boss_idx, new_boss_rem, new_cooldown) # 如果这个技能使用状态更优,则加入队列 if new_state_key not in visited or visited[new_state_key] > new_round: visited[new_state_key] = new_round # 重新计算启发式值 total_remaining = new_boss_rem + sum(B[new_boss_idx+1:]) estimate_rounds = math.ceil(total_remaining / max_avg) if max_avg > 0 else 0 new_f = new_round + estimate_rounds heapq.heappush(queue, (new_f, new_round, new_boss_idx, new_boss_rem, new_cooldown, new_boss_paths)) return None # 无解 if __name__ == '__main__': # 测试用例 B = [10, 20, 30, 40, 50] PlayerSkills = [(5, 2), (8, 3), (3, 1)] print("Boss血量序列:", B) print("玩家技能 (伤害, 冷却):", PlayerSkills) print() result = boss_fight(B, PlayerSkills) for i in result: print(i) # if result: # print("每个Boss的最优攻击序列:") # for i, boss_sequence in enumerate(result): # print(f"Boss {i+1} (血量{B[i]}): {boss_sequence}") # # 显示详细的技能使用说明 # skill_details = [] # total_damage = 0 # for action in boss_sequence: # if action == -1: # skill_details.append("等待") # else: # damage, cooldown = PlayerSkills[action] # total_damage += damage # skill_details.append(f"技能{action}(伤害{damage},冷却{cooldown})") # print(f" 详细: {' -> '.join(skill_details)}") # print(f" 总伤害: {total_damage}, Boss血量: {B[i]}") # print() # else: # print("无解 - 无法击败所有Boss")