ด้วยการแทนที่แต่ละครั้ง (ยกเว้นการแทนที่โดยตรงกับพาเรนต์ - ลูก) คุณเพิ่มความสัมพันธ์แบบบรรพบุรุษ - ลูกหลานใหม่ซึ่งทำให้ไม่ยุ่งยากในการพิจารณาว่าอันใดที่สมควรได้รับในระยะยาว ดังนั้นอัลกอริทึมโลภแบบง่ายจะล้มเหลวในกรณีทั่วไป อย่างไรก็ตามหากคุณใช้วิธีการเดรัจฉานบังคับคุณสามารถกำหนดกราฟที่เล็กที่สุด:
Python-ish (ไม่ได้ทดสอบ):
def play((V,E),F,sequence=[]):
"""
(V,E) -- a dag.
V -- a set of vertices.
E -- a set of directed-edge-tuples.
F -- a function that takes a vertex, returns an integer.
sequence -- the sequence of moved taken so far; starts with/defaults to
an empty list, will contain tuples of the form (x,y)
where x is removed and replaced with y.
Returns the best recursively found solution.
"""
#find all the integer values in the graph, remember which
# values correspond to what vertices. Of the form {integer => {vertices}}.
n2v = {}
for x in V:
n = F(x)
#for each integer, make sure you have a set to put the vertices in.
if n not in n2v:
n2v[n] = set()
#for each integer, add the vertex to the equivalent set.
n2v[n].add(v)
#record the best sequence/solution. You start with the current sequence,
# and see if you can obtain anything better.
best_solution = list(sequence)
#Now you will try to combine a single pair of vertices, obtain a new
# graph and then recursively play the game again from that graph.
#for each integer and equivalent set of vertices,
for n,vset in n2v.iteritems():
#pick a pair of vertices
for x in vset:
for y in vset:
#no point if they are the same.
if x == y:
continue
#If there is a path from x => y or y => x, then you will be
# introducing a cycle, breaking a rule. So in that case, disregard
# this pair.
#However, the exception is when one is a direct child of the other;
# in that case you can safely combine the vertices.
if pathtest((V,E),x,y) and (x,y) not in E and (x,y) not in E:
continue
#combine the vertices (function is defined below), discard x,
# replace it with y, obtain the new graph, (V',E').
Vp,Ep = combine_vertex((V,E),x,y))
#record the sequence for this move.
sequencep = list(sequence) + [(x,y)]
#recurse and play the game from this new graph.
solution = play(Vp,Ep,F,sequencep)
#if the returned solution is better than the current best,
if len(solution) > len(best_solution):
#record the new best solution
best_solution = solution
#return the best recorded solution
return best_solution
def combine_vertex((V0,E0),x,y):
"""
(V0,E0) -- an initial digraph.
V0 -- a set of vertices.
E0 -- a set of directed-edge-tuples.
x -- vertex to discard.
y -- vertex to replace it with.
returns a new digraph replacing all relationships to and from x to relate
to y instead, and removing x from the graph entirely.
"""
#the final vertex set will have everything except x
V = set(V0)
V.discard(x)
#now you construct the edge set.
E = set()
#for every edge,
for (u0,v0) in E0:
#recreate the edge in the new graph, but replace any occurence
# of x.
u,v = u0,v0
#if x is in the edge: replace it
if u == x:
u = y
if v == x:
v == y
#sometimes u=v=y and can now be pointing to itself, don't add that
# edge
if u == v:
continue
#add the new/replaced edge into the edge-set.
E.add( (u,v) )
return (V,E)
ฉันไม่แน่ใจว่ามันเป็นปัญหาจริงหรือไม่ แต่การเล่นด้วยกราฟบางอย่างด้วยตนเองดูเหมือนว่าจะเป็น combinatorial มาก ฉันอยากรู้ว่าสิ่งที่ยากสามารถลดปัญหานี้ได้หรือถ้ามีอัลกอริทึมที่มีเวลาทำงานที่ดีขึ้น