import math, time, random
from itertools import permutations
def rot(m, k):
mlen = len(m)
if k == 0: return m
return \[m\[(i-k)%mlen(j-k)%mlen for j in range(mlen)] for i in range(mlen)]
def cs(m, ker):
ml, kl = len(m), len(ker)
res = 0
for i in range(ml - kl + 1):
for ki in range(kl):
res += mi+kii+ki * kerkiki
return res
def tsp(b52, s, e, k):
st = time.time()
n = len(b52)
d = \[0*n for _ in range(n)]
for i in range(n):
x1, y1 = b52i
for j in range(i+1, n):
x2, y2 = b52j
dist = int(math.hypot(x1-x2, y1-y2))
dij = dji = dist
sidx = \[\]
for i in range(n):
r = (d\[ij, j) for j in range(n) if j != i]
r.sort()
sidx.append(idx for _, idx in r)
wm = \[\]
for c in range(n):
o = sidxc
m = n-1
mat = \[0*m for _ in range(m)]
for i in range(m):
for j in range(m):
if i != j: matij = 1 if oi > oj else 0
wm.append(mat)
ce = \[set() for _ in range(n) for __ in range(n)]
cf = [
\[0.5, -0.5\], \[-0.5, 0.5\]
] + [
\[0.5, -0.5, 0.5\], \[-0.5, 0.5, -0.5\], \[0.5, -0.5, 0.5\]
]
for fl in cf:
ns = \[\]
for c in range(n):
mat = wmc
sc = (cs(rot(mat, r), fl), r) for r in range(n-1)
sc.sort(reverse=True)
ns.append(sc:k)
for i in range(n):
for sc, r in nsi:
j = sidxir
ceij.add(r)
if len(ceij) > k:
ceij = set(list(ceij):k)
ec = \[\[ for _ in range(n)] for __ in range(n)]
for i in range(n):
if i != s:
for j in range(n):
if i != j and ceij:
for r in sorted(list(ceij)):k:
ecij.append(sidxir)
p = s
v = False*n
vs = True
for _ in range(n-1):
u = p-1
nn = vb for vl in ec\[u for vb in vl if vb and not vvb]
if not nn:
nn = vb for vb in range(n) if not v\[vb]
p.append(nn0)
vp\[-1] = True
p.append(e)
def cpd(pth):
return sum(dpth\[i]pth\[i+1] for i in range(len(pth)-1))
bd = cpd(p)
imp = True
mx = 1000
cnt = 0
while imp and cnt < mx:
imp = False
cnt += 1
for i in range(1, len(p)-2):
for j in range(i+1, len(p)-1):
dt = dp\[i-1]p\[j] + dp\[i]p\[j+1] - dp\[i-1]p\[i] - dp\[j]p\[j+1]
if dt < 0:
pi:j+1 = pi:j+1::-1
bd += dt
imp = True
return bd, p, time.time()-st,n
def c(p, e, D):
return sum(Dp\[i]p\[i+1] for i in range(len(p)-1)) + Dp\[-1]e
def g(k, ei):
el, ci = len(ei), 0
eg = {u: \[\] for u in range(k)}
for (u, v), i in ei.items():
egu.append(i)
ud = set()
for ids in eg.values():
for i in ids:
while True:
pb = (i << 1) | random.getrandbits(1)
if pb not in ud:
ud.add(pb)
ci |= (pb & 1) << i
break
if k >= 2:
u1, u2 = random.sample(range(k), 2)
df = len(egu1) - len(egu2)
if abs(df) <= math.isqrt(k):
elc = int(abs(math.sin(k) * df))
if elc > 0:
src = u2 if df > 0 else u1
ai = random.sample(egsrc, min(elc, len(egsrc)))
ci |= sum(1 << i for i in ai) if df > 0 else ~sum(1 << i for i in ai)
ec = {}
ci %= 1 << el
for (u, v), i in ei.items():
ec(u, v) = ec(v, u) = (ci >> i) & 1
return ec
def o(p, D):
imp = True
while imp:
imp = False
for i in range(1, len(p) - 2):
for k in range(i + 2, len(p)):
if Dp\[i-1]p\[i] + Dp\[k-1]p\[k] > Dp\[i-1]p\[k-1] + Dp\[i]p\[k]:
pi:k = pi:k::-1
imp = True
return p
berlin52=(565.0,575.0),(25.0,185.0),(345.0,750.0),(945.0,685.0),(845.0,655.0),(880.0,660.0),(25.0,230.0),(525.0,1000.0),(580.0,1175.0),(650.0,1130.0),(1605.0,620.0),(1220.0,580.0),(1465.0,200.0),(1530.0,5.0),(845.0,680.0),(725.0,370.0),(145.0,665.0),(415.0,635.0),(510.0,875.0),(560.0,365.0),(300.0,465.0),(520.0,585.0),(480.0,415.0),(835.0,625.0),(975.0,580.0),(1215.0,245.0),(1320.0,315.0),(1250.0,400.0),(660.0,180.0),(410.0,250.0),(420.0,555.0),(575.0,665.0),(1150.0,1160.0),(700.0,580.0),(685.0,595.0),(685.0,610.0),(770.0,610.0),(795.0,645.0),(720.0,635.0),(760.0,650.0),(475.0,960.0),(95.0,260.0),(875.0,920.0),(700.0,500.0),(555.0,815.0),(830.0,485.0),(1170.0,65.0),(830.0,610.0),(605.0,625.0),(595.0,360.0),(1340.0,725.0),(1740.0,245.0)
print("TSP问题求解 - 柏林52个城市")
print("正在计算基础解...")
s=0
se=0
base_dist, base_path, base_time,n = tsp(berlin52, s, se, 1000)
d = \[0*n for _ in range(n)]
for i in range(n):
x1, y1 = berlin52i
for j in range(i+1, n):
x2, y2 = berlin52j
dij = dji = ((x1 - x2)**2 + (y1 - y2)**2)**0.5
print(f"基础解距离: {base_dist:.2f}, 耗时: {base_time:.4f}s")
print(f"基础路径: {base_path}")
st = time.time()
dt0 = sorted((di0, i) for i in range(1, n))
df0 = sorted((d0i, i) for i in range(1, n))
rt0 = {idx: r+1 for r, (_, idx) in enumerate(dt0)}
rf0 = {idx: r+1 for r, (_, idx) in enumerate(df0)}
vn = \[\]
for i in range(1, n):
a, b = rt0i, rf0i
fd = False
for m in range(1, b):
for t in range(1, 3):
if (m * (a**t)) % b == 0:
vn.append(i)
fd = True
break
if fd:break
vn = vn if vn else list(range(1, n))
bp = base_path
bd = base_dist
ei = {}
idx = 0
for i in range(n):
for k in range(i+1, n):
ei(i, k) = idx
idx += 1
opt2_cnt = 0
for _ in range(50):
random.seed()
for _ in range(50):
ec = g(n, ei)
random.shuffle(vn)
p = s + vn + se
gss = \[ for _ in range(2)]
for nd in vn:gssec.get((nd % n, (nd + 1) % n), 0).append(nd)
np = s
for gs in gss:
if gs:np.extend(random.sample(gs, len(gs)))
np.append(se)
cd = c(np, se, d)
if cd < bd * 4:
np = o(np, d)
opt2_cnt += 1
cd = c(np, se, d)
if cd < bd:
bd = cd
bp = np
print(f"\n优化后结果:")
print(f"{n}节点 起点:{s} 终点:{se}")
print(f"最优路径: {bp}")
print(f"最优距离: {bd}")
print(f"总时间: {time.time()-st:.2f}s")
print(f"opt2调用次数: {opt2_cnt}")