学习华为上机测试题,遇见了下面题,很有意思,核心是匈牙利算法问题。
特此学习记录。资料均参考自网络。
匈牙利算法目的:找出两边最大的匹配的数量。
参考资料:
https://blog.csdn.net/u013377068/article/details/79893013
https://blog.csdn.net/sunny_hun/article/details/80627351
https://www.nowcoder.com/profile/8408989/codeBookDetail?submissionId=25842225
题目描述:
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的N(N为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
输入:有一个正偶数N(N≤100),表示待挑选的自然数的个数。后面给出具体的数字,范围为[2,30000]。
输出:输出一个整数K,表示你求得的“最佳方案”组成“素数伴侣”的对数。
输入说明:1 输入一个正偶数n, 2输入n个整数
输出描述: 求得的“最佳方案”组成“素数伴侣”的对数。
# In[]
# 匈牙利算法
# 别人代码
def prime_judge(n): #判断一个数是否是素数
m=int(n**0.5)
if n%2==0:
return False
else:
for i in range(m+1)[3::2]:
if n%i==0:
return False
return True
def group_lst(lst): #判断列表内数为奇偶数,并分开存放
a = []
b = []
for i in lst:
if int(i)%2 == 1:
a.append(int(i))
else:
b.append(int(i))
return (a, b)
def matrix_ab(a, b): #构建一个a行b列的二维矩阵,矩阵内容为1表示a+b为素数,为0表示a+b不是素数
matrix = [[0 for i in range(len(b))] for i in range(len(a))]
for ii, i in enumerate(a):
for jj, j in enumerate(b):
if prime_judge(i+j) == True:
matrix[ii][jj] = 1
return matrix
def find(x): #匈牙利算法匹配
for index, i in enumerate(b):
if matrix[x][index] == 1 and used[index] == 0: # 男女有好感 且 这个女的还没有和男的匹配过
used[index] = 1
if connect[index] == -1 or find(connect[index]) != 0: # 如果这个女的还单身 或者 这个女的已经配好的男的还能去找别的女的(递归)
connect[index] = x # 匹配成功 第x号男的 和 第index号女的
return 1
return 0
while True: #理解a,b为男女配对的话
try:
n = int(input())
m = input().split()
(a, b) = group_lst(m)
matrix = matrix_ab(a, b)
connect = [-1 for i in range(len(b))] #标记这个女的是否已经配对成功
count = 0
for i in range(len(a)):
used = [0 for j in range(len(b))] # 女的是否被这个男的查找过了
if find(i): #从当前男的开始查找
count += 1 # 配对成功+1(这个男女的配对可能会变,但是数量不变)
print(count)
except:
break