1.实验目的
寻找飞行员配对中的最大匹配:
2.实验内容
2.1问题描述
第二次世界大战时期, 英国皇家空军从沦陷国征募了大量外籍飞行员。 由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员, 其中 1 名是英国飞行员,另 1 名是外籍飞行员。 在众多的飞行员中, 每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。 如何选择配对飞行的飞行员才能使一次派出最多的飞机。 对于给定的外籍飞行员与英国飞行员的配合情况, 试设计一个算法找出最佳飞行员配对方案, 使皇家空军一次能派出最多的飞机。
2.2问题分析
这是一个二分图匹配问题,【英国飞行员】和【外籍飞行员】可以看作是二分图中两个不相交的点集X,Y。其中外籍飞行员可以任意与其他若干英国飞行员配合可以看作X点集中的点有若干条边与Y中的点相连。
每一条相连的边可以看作这两名飞行员能互相配合。
求最佳飞行员配对方案,就是求这个二分图的最大匹配。
3.实验过程
3.1 数据输入
设有N个英国飞行员,M个外籍飞行员,英国飞行员与外籍飞行员匹配情况如下:
英国飞行员\ 外籍飞行员 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
2 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
3 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
4 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
6 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
graph = [(1,0,1,0,1,1,1,0,0),
(0,1,1,1,0,0,0,1,1),
(0,1,0,0,0,1,1,0,0),
(1,0,0,0,1,0,1,0,0),
(0,0,0,1,0,0,0,0,1),
(1,0,0,0,1,0,0,0,0),
(0,0,0,1,0,0,1,0,0)]
3.2 实验思路及代码
实验中采用广度优先算法去寻找匹配边,思路主要是一个“让”的过程。
-
-如果Y没有匹配过任何X,则X与Y互相匹配。
-
-或者Y匹配过其他X,但与Y相连的其他X能找到其他匹配:
那么就把当前Y点让给当前X,当前Y和X互相标记。
曾标记过Y的X去寻找其他匹配。
代码如下: -
1.寻找匹配边
def find(self, x):
for y in range(self.l):
if self.graph[x][y] == 1 and not self.used[y]:
self.used[y] = 1
if self.match[y] == -1 or self.find(self.match[y]) == 1:
self.match[y] = x
self.match[x] = y
return 1
return 0
- 2.递归调用find
def hungarian(self):
"""递归形式"""
self.match = [-1] * self.l # 记录匹配情况
self.used = [False] * self.l # 记录是否访问过
m = 0
for x in range(self.n):
if self.match[x] == -1:
self.used = [False] * self.l
print('开始匹配点X{}'.format(x + 1))
m += self.find(x)
return m
实验结果
4. 存在问题即解决方法
无