|
让deepseek分别生成了 https://www.mersenneforum.org/node/17331/ 中的思路和 c++程序思路的python 代码,还是前者快一点
- import math
- from collections import defaultdict
- def generate_vertices(b):
- """生成顶点集合(单元素数组 + 35元素数组及其翻转)"""
- vertices = []
- # 单元素顶点(1-12)
- for c in range(1, 13):
- vertices.append({
- "array": [c],
- "type": "single",
- "c": c,
- "reversed": False,
- "id": f"single_{c}"
- })
- # 35元素顶点(c从-12到12,包括0)
- for c in range(-12, 13):
- v = [25 * b[i] + c * ((-1) ** i) for i in range(len(b))]
- vertices.append({
- "array": v,
- "type": "complex",
- "c": c,
- "reversed": False,
- "id": f"c{c}_orig"
- })
- vertices.append({
- "array": v[::-1],
- "type": "complex",
- "c": c,
- "reversed": True,
- "id": f"c{c}_rev"
- })
- return vertices
- def is_square_sum(a, b):
- """检查两个数之和是否为完全平方数"""
- s = a + b
- return s >= 0 and int(math.sqrt(s)) ** 2 == s
- def build_adjacency_list(vertices):
- """构建邻接表并预计算原始度数"""
- adj = defaultdict(list)
- degrees = defaultdict(int)
- for i, u in enumerate(vertices):
- for j, v in enumerate(vertices):
- if i == j:
- continue
- if is_square_sum(u["array"][-1], v["array"][0]):
- adj[i].append(j)
- degrees[i] += 1 # 记录原始度数
- return adj, degrees
- def dynamic_degree(current, adj, visited):
- """动态计算邻接节点的有效度数(未使用的邻接数)"""
- neighbor_degrees = []
- for neighbor in adj[current]:
- if neighbor in visited:
- continue
- # 计算该邻居未使用的邻接数
- valid_links = sum(1 for n in adj[neighbor] if n not in visited)
- neighbor_degrees.append( (neighbor, valid_links) )
-
- # 按有效度数升序排序
- return sorted(neighbor_degrees, key=lambda x: x[1])
- def backtrack_search(vertices, adj, degrees, max_steps=1e6):
- """优化后的回溯搜索,优先选择低度数节点"""
- # 定位起点[1]和终点[3]
- start = next(i for i, v in enumerate(vertices) if v["c"] == 1 and v["type"] == "single")
- end = next(i for i, v in enumerate(vertices) if v["c"] == 3 and v["type"] == "single")
-
- # 初始化状态跟踪
- visited = set([start])
- path = [start]
- used_single = {1}
- used_c = set()
- step_counter = [0]
- result = None
-
- def recurse(current, used_single, used_c):
- step_counter[0] += 1
- if step_counter[0] > max_steps:
- print(step_counter[0])
- return "overflow"
-
- # 终止条件:12个单元素 + 25个35元素数组
- if len(path) == 37: # 12单元素 + 25复杂数组
- if current == end and is_square_sum(vertices[path[-1]]["array"][-1], vertices[path[0]]["array"][0]):
- return path.copy()
- return None
-
- # 动态计算当前邻接节点的有效度数并排序
- neighbors = dynamic_degree(current, adj, visited)
-
- # 优先尝试低度数节点
- for neighbor, _ in neighbors:
- vertex = vertices[neighbor]
-
- # 检查顶点使用规则
- if vertex["type"] == "single":
- if vertex["c"] in used_single:
- continue
- new_used_single = used_single | {vertex["c"]}
- new_used_c = used_c
- else:
- if vertex["c"] in used_c:
- continue
- new_used_c = used_c | {vertex["c"]}
- new_used_single = used_single
-
- # 提前剪枝:最后一步必须是终点
- if len(path) == 36 and neighbor != end:
- continue
-
- # 更新状态
- visited.add(neighbor)
- path.append(neighbor)
- ret = recurse(neighbor, new_used_single, new_used_c)
-
- if ret == "overflow":
- return ret
- if ret is not None:
- return ret
-
- # 回溯
- path.pop()
- visited.remove(neighbor)
-
- return None
-
- # 执行搜索
- result = recurse(start, used_single, used_c)
-
- if result == "overflow":
- print(f"达到最大递归次数 {max_steps},未找到解")
- return None
- return [vertices[i]["array"] for i in result] if result else None
- # ---------- 执行程序 ----------
- if __name__ == "__main__":
- # 输入参数
- b = [1,8,28,21,4,32,17,19,6,30,34,15,10,26,23,13,12,24,25,11,5,20,29,35,14,2,7,18,31,33,16,9,27,22,3]
-
- # 生成图结构
- vertices = generate_vertices(b)
- adj, degrees = build_adjacency_list(vertices)
-
- # 执行搜索(可根据需要调整max_steps)
- path = backtrack_search(vertices, adj, degrees, max_steps=500_000)
-
- if path:
- print("找到哈密顿回路:")
- full_path=[]
- for i, arr in enumerate(path):
- full_path+=arr
- #print(f"Step {i+1}: {arr}")
- print(full_path)
- else:
- print("未找到有效路径")
复制代码
c++思路
- import math
- import time
- from collections import defaultdict
- class Graph:
- def __init__(self, V):
- self.V = V # 顶点数
- self.adj = [0] * V # 邻接表(使用位运算表示)
- self.cnt = 0 # 递归计数器
- def add_edge(self, u, v):
- """添加边(无向图)"""
- self.adj[u] |= 1 << v
- self.adj[v] |= 1 << u
- def hamiltonian_cycle_util(self, path, visited, pos, start):
- """回溯工具函数,寻找哈密顿回路"""
- self.cnt += 1
- if self.cnt > 100_000: # 递归次数超过 100,000 次,直接返回
- return False
- # 终止条件:路径包含所有顶点且首尾相连
- if pos == self.V:
- if self.adj[path[pos - 1]] & (1 << start):
- return True
- return False
- # 获取当前顶点的未访问邻接顶点
- neighbors = self.adj[path[pos - 1]] & ~visited
- # 按未使用的邻接点数量排序(动态度数排序)
- neighbor_list = []
- for v in range(self.V):
- if neighbors & (1 << v):
- # 计算 v 的未使用邻接点数量
- valid_links = bin(self.adj[v] & ~visited).count("1")
- neighbor_list.append((v, valid_links))
- # 按未使用的邻接点数量升序排序
- neighbor_list.sort(key=lambda x: x[1])
- # 尝试每个邻接顶点
- for v, _ in neighbor_list:
- # 如果未到最后一步,且 v 是起点的最后一个邻接点,则跳过
- if pos != self.V - 1 and v == start and bin(self.adj[path[pos - 1]]).count("1") == 1:
- continue
- path[pos] = v
- visited |= 1 << v # 标记为已访问
- if self.hamiltonian_cycle_util(path, visited, pos + 1, start):
- return True
- visited &= ~(1 << v) # 回溯
- return False
- def hamiltonian_cycle(self):
- """寻找哈密顿回路"""
- path = [-1] * self.V
- visited = 0 # 使用位运算表示访问状态
- # 尝试从每个起点开始
- for s in range(self.V):
- self.cnt = 0 # 重置递归计数器
- path = [-1] * self.V
- visited = 0
- # 从顶点 s 开始
- path[0] = s
- visited |= 1 << s
- if self.hamiltonian_cycle_util(path, visited, 1, s):
- return path
- return None
- # ---------- 主程序 ----------
- if __name__ == "__main__":
- # 输入参数
- n = 887 # 顶点数
- b = [1, 8, 28, 21, 4, 32, 17, 19, 6, 30, 34, 15, 10, 26, 23, 13, 12, 24, 25, 11, 5, 20, 29, 35, 14, 2, 7, 18, 31, 33, 16, 9, 27, 22, 3]
- # 生成图
- G = Graph(n)
- # 构建图(根据平方和规则添加边)
- for i in range(1, n + 1):
- for j in range(i + 1, n + 1):
- s = i + j
- sqrt_s = int(math.isqrt(s))
- if sqrt_s * sqrt_s == s:
- G.add_edge(i - 1, j - 1) # 顶点编号从 0 开始
- # 计时开始
- start_time = time.time()
- # 查找哈密顿回路
- cycle = G.hamiltonian_cycle()
- # 计时结束
- elapsed_time = time.time() - start_time
- # 输出结果
- if cycle:
- print(f"哈密顿回路找到!递归调用次数: {G.cnt}, 耗时: {elapsed_time:.2f} 秒")
- print("回路:", [v + 1 for v in cycle]) # 恢复顶点编号
- else:
- print(f"未找到哈密顿回路。递归调用次数: {G.cnt}, 耗时: {elapsed_time:.2f} 秒")
复制代码 |
|