Here is a heuristic idea:
- . (, ), , 0 .
- ,
s1 s2, t. a1 a2, s1 s2. ( , s1 s2 - ), 2.t_sum , a1, , a2 t. t_sum t, (8 ), 2.a1 a2 . , . , a1 s1 a2 s2, , a1 s1 a2 s2, () a1, . t_sum.- 2. , .
. , , , , a1 a2, / . , :
a1 a2 s1 s2, a1 a2. , 1 2, [1, 3, 4] [2] ( [2, 1, 3, 4] [4, 3, 1, 2]), 1, , 2, .a1 a2, T - t_sum < t, ( t), "" ", , , ( ), a1 a2 3.- , , ,
t "" t, "" , .
EDIT:
Python. NumPy , , , , .
def make_journeys(dists, max_dist):
n = len(dists)
ds = sorted((dists[i][j], i, j) for i in range(n) for j in range(i + 1, n))
starts = list(range(n))
ends = list(range(n))
salesmen = [([i], 0) for i in range(n)]
for d, i, j in ds:
if starts[i] is not None and starts[j] is not None:
si, sj = starts[i], starts[j]
reverse_i, reverse_j = True, False
elif starts[i] is not None and ends[j] is not None:
si, sj = starts[i], ends[j]
reverse_i, reverse_j = True, True
elif ends[i] is not None and starts[j] is not None:
si, sj = ends[i], starts[j]
reverse_i, reverse_j = False, False
elif ends[i] is not None and ends[j] is not None:
si, sj = ends[i], ends[j]
reverse_i, reverse_j = False, True
else:
continue
if si == sj:
continue
(pi, di) = salesmen[si]
(pj, dj) = salesmen[sj]
dt = d + di + dj
if dt > max_dist:
continue
starts[pi[0]] = None
ends[pi[-1]] = None
starts[pj[0]] = None
ends[pj[-1]] = None
if reverse_i:
pi = list(reversed(pi))
if reverse_j:
pj = list(reversed(pj))
pt = pi + pj
starts[pt[0]] = si
ends[pt[-1]] = si
salesmen[si] = (pt, dt)
salesmen[sj] = None
return [s for s in salesmen if s]
. :
def random_symmetric(N, min, max):
dists = [[random.randint(1, 9) if i != j else 0 for j in range(N)] for i in range(N)]
return [[(dists[i][j] + dists[j][i]) // 2 for j in range(N)] for i in range(N)]
random.seed(100)
distances = random_symmetric(5000, 1, 9)
max_distance = 100
journeys = make_journeys(distances, max_distance)
print('{} journeys computed.'.format(len(journeys)))
:
50 journeys computed.
( NumPy). make_journeys ~ 16 . , YMMV, .