相关原理

详见这里

简单来说, 子帕鲁是两个父帕鲁繁殖力与1的和整除2, 特殊配方需要按照专有配方才可以繁殖

剪枝的 bfs 即可完成

准备数据

你需要从帕鲁编年史中, 自行整理 a.tsv (所有帕鲁的CombiRank 繁殖力 IndexOrder 索引), b.tsv (特殊繁殖配方)

此索引与帕鲁id不同

两个表的格式示例

a.tsv

帕鲁编年史 Breed Combi

name	CombiRank	IndexOrder
皮皮鸡	1500	66
壶小象	1490	17
喵丝特	1480	7

注意中间是 \t 制表符

b.tsv

帕鲁编年史 Breed Unique
帕鲁编年史 Breed Self

parent	孵化完成
佩克龙  伏特喵	派克龙
炎魔羊  噬魂兽	暗魔羊
喵丝特  企丸丸	冰丝特

注意中间是 \t 制表符, parent中间是两个空格

注意语言

代码

未整理代码

from collections import deque
import csv

def load_data():
    data = {}
    with open(r'a.tsv', 'r', newline='', encoding='utf-8') as f:
        reader = csv.reader(f, delimiter='\t')
        next(reader)
        for row in reader:
            data[row[0]] = {"fertility": int(row[1]), "index_order": int(row[2])}

    data2 = {}
    exclusive = set()

    with open(r'b.tsv', 'r', newline='', encoding='utf-8') as f:
        reader = csv.reader(f, delimiter='\t')
        next(reader)
        for row in reader:
            parents = tuple(sorted(row[0].split('  ')))
            child = row[1]
            data2[parents] = child
            exclusive.add(child)

    return data, data2, exclusive

pal_data, special_breeding, exclusive_pals = load_data()

def breed(parent1, parent2):
    key = tuple(sorted([parent1, parent2]))
    if key in special_breeding:
        return special_breeding[key]
    
    # 塔主处理
    p1_fertility = pal_data[parent1]["fertility"]
    p2_fertility = pal_data[parent2]["fertility"]
    if p1_fertility == 9999 or p2_fertility == 9999:
        return "皮皮鸡"
    
    value = (p1_fertility + p2_fertility + 1) // 2
    
    valid_pals = [
        (name, info) for name, info in pal_data.items() 
        if name not in exclusive_pals
    ]
    
    closest_pal = min(
        valid_pals,
        key=lambda x: (abs(x[1]["fertility"] - value), x[1]["index_order"])
    )
    return closest_pal[0]

def find_breeding_path(start, end):
    if start not in pal_data or end not in pal_data:
        return []
    
    target_fertility = pal_data[end]["fertility"]
    visited = {}
    queue = deque([(start, [start])])
    results = []
    min_steps = None

    while queue:
        level_size = len(queue)
        found = False
        
        for _ in range(level_size):
            current_pal, path = queue.popleft()
            
            if min_steps and len(path) > min_steps:
                continue
                
            if current_pal == end:
                if not min_steps:
                    min_steps = len(path)
                if len(path) == min_steps:
                    results.append(path)
                found = True
                continue
                
            # 获取当前帕鲁繁殖力
            current_fertility = pal_data[current_pal]["fertility"]
            
            for mate in pal_data:
                if mate == current_pal:
                    continue
                
                key = tuple(sorted([current_pal, mate]))
                
                # 特殊繁殖直接处理
                if key in special_breeding:
                    child = special_breeding[key]
                    new_path = path + [mate, child]
                    if child not in visited or len(new_path) < visited.get(child, float('inf')):
                        visited[child] = len(new_path)
                        queue.append((child, new_path))
                    continue
                
                mate_fertility = pal_data[mate]["fertility"]
                
                # 塔主特殊处理
                if current_fertility == 9999 or mate_fertility == 9999:
                    child = "皮皮鸡"
                else:
                    if current_fertility < target_fertility and mate_fertility < current_fertility:
                        continue  # 配偶生育力更低,子代只会更小
                    if current_fertility > target_fertility and mate_fertility > current_fertility:
                        continue  # 配偶生育力更高,子代只会更大
                    
                    child = breed(current_pal, mate)
                
                new_path = path + [mate, child]
                
                # 如果子代生育力偏离目标方向
                child_fertility = pal_data[child]["fertility"]
                if (target_fertility > current_fertility and child_fertility < current_fertility) or \
                   (target_fertility < current_fertility and child_fertility > current_fertility):
                    continue
                
                if child not in visited or len(new_path) < visited[child]:
                    visited[child] = len(new_path)
                    queue.append((child, new_path))
                elif len(new_path) == visited[child]:
                    queue.append((child, new_path))
        
        if found:
            break

    final_results = [p for p in results if len(p) == min_steps]
    return final_results if final_results else []

start_pal = "混沌骑士"
end_pal = "八云犬"
paths = find_breeding_path(start_pal, end_pal)

if paths:
    print(f"找到{len(paths)}条最短繁殖路径(步数:{(len(paths[0])-1)//2}):")
    for i, path in enumerate(paths, 1):
        print(f"\n路径{i}:")
        for j in range(0, len(path)-1, 2):
            print(f"{path[j]} + {path[j+1]}{path[j+2]}")
else:
    print("无可行繁殖路径")

不知道为什么, 相对于帕鲁编年史的实现, 我的实现慢一点, 估计是他预计算好了

转载无需注明出处