Python 16 + 15 + 14 + 20 + 12 = 77
ฉันไม่เคยมีประสบการณ์มาก่อนเกี่ยวกับปัญหาประเภทพนักงานขายที่เดินทาง แต่ฉันมีเวลาอยู่ในมือของฉันดังนั้นฉันคิดว่าฉันจะให้มันยิง โดยทั่วไปแล้วมันพยายามที่จะจัดสรรบอทผักดองบางชนิดโดยการเดินมันแม้ว่าจะเป็นการวิ่งขั้นต้นที่พวกเขาจะไปหาคนที่อยู่ใกล้พวกเขามากที่สุดและไกลที่สุดจากคนอื่น ๆ จากนั้นมันจะบังคับวิธีที่มีประสิทธิภาพที่สุดสำหรับแต่ละบอทเพื่อรวบรวมผักดองที่ได้รับมา
ฉันไม่รู้ว่าวิธีนี้ใช้ได้จริง แต่ฉันคิดว่ามันจะไม่ทำงานได้ดีสำหรับบอร์ดขนาดใหญ่ที่มีบอทน้อยลง (บอร์ดที่สี่บางครั้งใช้เวลากว่าสองนาที)
รหัส:
def parse_input(string):
pickles = []
size = len(string) - string.count('\n')
poses = [None] * (size - string.count('.') - string.count('P'))
for y,line in enumerate(string.strip().split('\n')):
for x,char in enumerate(line):
if char == '.':
continue
elif char == 'P':
pickles.append((x,y))
else:
poses[int(char)-1] = (x,y)
return pickles, poses
def move((px,py),(tx,ty)):
if (px,py) == (tx,ty):
return (px,py)
dx = tx-px
dy = ty-py
if abs(dx) <= abs(dy):
if dy < 0:
return (px,py-1)
else:
return (px,py+1)
else:
if dx < 0:
return (px-1,py)
else:
return (px+1,py)
def distance(pos, pickle):
return abs(pos[0]-pickle[0]) + abs(pos[1]-pickle[1])
def calc_closest(pickles,poses,index):
distances = [[distance(pos,pickle) for pickle in pickles] for pos in poses]
dist_diffs = []
for i, pickle_dists in enumerate(distances):
dist_diffs.append([])
for j, dist in enumerate(pickle_dists):
other = [d[j] for d in distances[:i]+distances[i+1:]]
dist_diffs[-1].append(min(other)-dist)
sorted = pickles[:]
sorted.sort(key = lambda ppos: -dist_diffs[index][pickles.index(ppos)])
return sorted
def find_best(items,level):
if level == 0:
best = (None, None)
for rv, rest in find_best(items[1:],level+1):
val = distance(items[0],rest[0]) + rv
if best[0] == None or val < best[0]:
best = (val, [items[0]] + rest)
return best
if len(items) == 1:
return [(0,items[:])]
size = len(items)
bests = []
for i in range(size):
best = (None, None)
for rv, rest in find_best(items[:i]+items[i+1:],level+1):
val = distance(items[i],rest[0]) + rv
if best[0] == None or val < best[0]:
best = (val, [items[i]] + rest)
if best[0] != None:
bests.append(best)
return bests
def find_best_order(pos,pickles):
if pickles == []:
return 0,[]
best = find_best([pos]+pickles,0)
return best
def walk_path(pos,path):
history = ''
while path:
npos = move(pos, path[0])
if npos == path[0]:
path.remove(path[0])
if npos[0] < pos[0]:
history += 'L'
elif npos[0] > pos[0]:
history += 'R'
elif npos[1] < pos[1]:
history += 'U'
elif npos[1] > pos[1]:
history += 'D'
pos = npos
return history
def find_paths(input_str):
pickles, poses = parse_input(input_str) ## Parse input string and stuff
orig_pickles = pickles[:]
orig_poses = poses[:]
numbots = len(poses)
to_collect = [[] for i in range(numbots)] ## Will make a list of the pickles each bot should go after
waiting = [True] * numbots
targets = [None] * numbots
while pickles:
while True in waiting: ## If any bots are waiting for a new target
index = waiting.index(True)
closest = calc_closest(pickles,poses,index) ## Prioritizes next pickle choice based upon how close they are RELATIVE to other bots
tar = closest[0]
n = 0
while tar in targets[:index]+targets[index+1:]: ## Don't target the same pickle!
other_i = (targets[:index]+targets[index+1:]).index(tar)
dist_s = distance(poses[index],tar)
dist_o = distance(poses[other_i],tar)
if dist_s < dist_o:
waiting[other_i] = True
break
n += 1
if len(closest) <= n:
waiting[index] = False
break
tar = closest[n]
targets[index] = tar
waiting[index] = False
for i in range(numbots): ## Move everything toward targets (this means that later target calculations will not be based on the original position)
npos = move(poses[i], targets[i])
if npos != poses[i]:
poses[i] = npos
if npos in pickles:
to_collect[i].append(npos)
pickles.remove(npos)
for t, target in enumerate(targets):
if target == npos:
waiting[t] = True
paths = []
sizes = []
for i,pickle_group in enumerate(to_collect): ## Lastly brute force the most efficient way for each bot to collect its allotted pickles
size,path = find_best_order(orig_poses[i],pickle_group)
sizes.append(size)
paths.append(path)
return max(sizes), [walk_path(orig_poses[i],paths[i]) for i in range(numbots)]
def collect_pickles(boards):
## Collect Pickles!
total = 0
for i,board in enumerate(boards):
result = find_paths(board)
total += result[0]
print "Board "+str(i)+": ("+ str(result[0]) +")\n"
for i,h in enumerate(result[1]):
print '\tBot'+str(i+1)+': '+h
print
print "Total Score: " + str(total)
boards = """
P.......1.
..........
P.....P...
..P.......
....P2....
...P.P....
.PP..P....
....P....P
PPPP....3.
.P..P.P..P
....P.....
P....1....
.P.....PP.
.PP....PP.
.2.P.P....
..P....P..
.P........
.....P.P..
P.....P...
.3.P.P....
..P..P..P.
..1....P.P
..........
.......2P.
...P....P3
.P...PP..P
.......P.P
..P..P..PP
..P.4P..P.
.......P..
..P...P...
.....P....
PPPP...P..
..P.......
...P......
.......P.1
.P..P....P
P2PP......
.P..P.....
..........
......PP.P
.P1..P.P..
......PP..
P..P....2.
.P.P3.....
....4..P..
.......PP.
..P5......
P.....P...
....PPP..P
""".split('\n\n')
collect_pickles(boards)
เอาท์พุท:
Board 0: (16)
Bot1: DLDLLLLDLLULUU
Bot2: LDLDLLDDLDRURRDR
Bot3: URDDLLLULULURU
Board 1: (15)
Bot1: ULRDRDRRDLDDLUL
Bot2: DDURURULLUUL
Bot3: ULRRDRRRURULRR
Board 2: (14)
Bot1: URRRDDDDDRLLUL
Bot2: UUURDRDDLD
Bot3: DDDLDDLUUU
Bot4: RULLLDUUUL
Board 3: (20)
Bot1: DLULUUUUULDLLLULDDD
Bot2: LURDDURRDRUUUULUULLL
Board 4: (12)
Bot1: LDDLDR
Bot2: ULUULRRR
Bot3: LUURURDR
Bot4: RRRDRDDDR
Bot5: LLDLRRRDRRRU
Total Score: 77