我喜欢编程挑战并尝试解决它们,然而,这个让我感到有点难过,我真的可以在正确的方向上使用一个点。
有一组数字,1到N代表女性,N + 1到2N代表男性。 (因此,如果N = 5那么这意味着1,2,3,4,5 =女性和6,7,8,9,10 =男性。)我试图找到可能的最大匹配量。虽然这是一个问题,女性数字是挑剔的,只会与他们的数字配对。所以它看起来像这样:
19
1: 25
2: 20 25 28
3: 27 32 37
4: 22
5: 32 38
6: 32 34 35
7: 22 34 37
8: 30 35 38
9: 20 23
10: 24 29
11: 29 32
12: 23 26 31
13: 21 25 34
14: 21 27
15: 20
16: 23 31 38
17: 22 27 28
18: 35
19: 24 25
所以“#:”是女孩的地方,你会说女孩#1只会和第25个人配对。同样,女孩#2只会与男性#20,25或28对。
我对此的解决方案是将每一行放入一个数组中,然后再创建一个已使用的空数组。我从女孩开始,她们只会与一个人配对并给他们配对。然后我去找那些只与2人一组中的人配对的女孩。最后是3.
这种方法效果不错,但是,这意味着有些人在可能的情况下没有配对,因此,由于它的先到先得的性质,我的最大配对数量未达到。< / p>
使用上面的例子,我得到16个中的16个(最多可能是17个),其中3个未配对的女孩是#13,17和19。
这是我目前的代码:
def findPairs(women):
pairs = []
taken = []
for woman in range(women):
data = raw_input()
#Remove the "#: " in each line and format numbers into ['1','2','3']
data = (data[len(str(woman))+2:]).split()
pairs.append(data)
for entry in pairs:
if len(entry) == 1:
if entry[0] not in taken:
taken.append(entry[0])
else:
print("No match for " + str(entry))
for entry in pairs:
if len(entry) == 2:
if entry[0] not in taken:
taken.append(entry[0])
elif entry[1] not in taken:
taken.append(entry[1])
else:
print("No match for " + str(entry))
for entry in pairs:
if len(entry) == 3:
if entry[0] not in taken:
taken.append(entry[0])
elif entry[1] not in taken:
taken.append(entry[1])
elif entry[2] not in taken:
taken.append(entry[2])
else:
print("No match for " + str(entry))
print(len(taken))
findPairs(input())
有没有人知道如何更好地优化我的配对匹配,以便我可以达到最大配对? (最好是一种可以扩展的方式,找到一种黑客方式来找到这些19的答案,如果它不适用于50个女孩的不同组合,那就没有太大的收获。但是可以假设格式很好将保持不变(即:每行最多3个人,更大到更大的顺序等等。)虽然能够使其尽可能地扩展是很酷的,但除了这个问题之外还有其他问题。 )
答案 0 :(得分:3)
以下是一个未经优化的实现,用于查找迭代所有不匹配女性的maximum-matching in a bipartite graph,并尝试通过将每个女性与其中一位候选人配对来尝试更改当前匹配,如下所示:
我将这个过程命名为#34;放松&#34;因为它有点提醒Dijkstra's algorithm中的递归放松步骤。
以下是代码:
import random
def read_file():
res = {}
start = True
with open('pairs.txt', 'r') as f:
for line in f.readlines():
if start:
start = False
continue
woman, matches = line.strip().split(': ')
woman = int(woman)
matches = map(int, matches.split(' '))
res[woman] = matches
return res
def build_random_match(graph):
edges = {}
for woman in graph:
for man in graph[woman]:
if already_in_edges(man, edges):
continue
else:
edges[woman] = man
break
return edges
def already_in_edges(man, edges):
for woman in edges:
if edges[woman] == man:
return True
else:
return False
def get_unmatched_women(match, graph):
return [woman for woman in graph.keys() if woman not in match.keys()]
def not_in_match(man, match):
for woman in match:
if match[woman] == man:
return False
else:
return True
def find_unmatched_man(graph, match, woman):
potentials = graph[woman]
for man in potentials:
if not_in_match(man, match):
return man
else:
return False
def remove_man_from_match(man, unmatched_woman, match, graph):
# find the woman that this man is currently matched with
# and cancel this matching
for woman in match:
if match[woman] == man:
match_to_del = woman
break
del match[match_to_del]
# also remove the man from the orig woman (graph)
# to prevent infinite loop
men = graph[unmatched_woman]
men.remove(man)
graph[unmatched_woman] = men
return match_to_del
def relax(unmatched_woman, match, graph):
unmatched_man = find_unmatched_man(graph, match, unmatched_woman)
if unmatched_man:
match[unmatched_woman] = unmatched_man
elif len(graph[unmatched_woman]) == 0:
return match
else:
# grab one of the possible matchings randomly
rand_index = random.randint(0, len(graph[unmatched_woman])-1)
man = graph[unmatched_woman][rand_index]
new_unmatched_woman = remove_man_from_match(man, unmatched_woman, match, graph)
match[unmatched_woman] = man
match = relax(new_unmatched_woman, match, graph)
return match
def improve_match(match, graph):
if len(match) == len(graph):
return match
unmatched_women = get_unmatched_women(match, graph)
for woman in unmatched_women:
copy_graph = graph.copy()
suggested = relax(woman, match, copy_graph)
if len(suggested) > len(match):
return suggested
else:
suggested = match
else:
return suggested
def main():
graph = read_file()
match = build_random_match(graph)
if len(match) == len(graph):
print 'Got a perfect match:', match
else:
match_size = 0
while match_size < len(match):
match_size = len(match)
match = improve_match(match, graph)
return match
if __name__ == '__main__':
res = main()
print "Size of match:", len(res)
print "Match:", res
输出:
Size of match: 17
Match: {2: 28, 3: 32, 4: 22, 5: 38, 6: 34, 7: 37, 8: 30, 9: 23, 10: 24, 11: 29, 12: 26, 13: 21, 15: 20, 16: 31, 17: 27, 18: 35, 19: 25}
答案 1 :(得分:0)
我不是Python开发人员,但这是我解决问题的方式。
将数据作为列表列表引入。使用女孩的数量作为指标。即女孩1是索引0,在该索引中存储人员列表。为数据创建一个巨大的列表列表。
遍历列表列表,找到女孩与一个人匹配的单场比赛。将单个对战(人)存储在列表中以进行迭代。然后遍历列表列表,从列表列表中删除单个匹配人员。然后重新开始。您的目标是将列表缩减为单个元素,并跟踪列表中的位置。