题目描述
题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如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个整数
输出描述:
求得的“最佳方案”组成“素数伴侣”的对数。
示例1
输入
4 2 5 6 13
输出
2
匈牙利算法解决二分图最大匹配问题
二分图:在图的概念里,可以把图中的点分成两部分,保证这两部分各自内部没有连线(在这道题里,素数伴侣只能是一个奇数一个偶数)
匈牙利算法过程(实例6 5 2 13)
(1)把输入的数据分成两部分偶数部分(6,2) 奇数部分(5,13)
(2)遍历奇数列表(最大的素数伴侣的数目是奇数的个数)
首先给5找到的伴侣是6,令matched[j]=5,j是偶数列表的游标
然后给13找伴侣,遍历偶数列表发现6也可以是13的伴侣,但是已经给5匹配了,于是就把6匹配给13,然后再获取之前matched的数,给这个数继续遍历偶数数组找伴侣,这个时候,不会取到6,因为6在used数组已经标记,找到2成功匹配。返回
匈牙利生动讲解:https://blog.csdn.net/Dark_Scope/article/details/8880547
package xidian.lili.test;
import java.util.ArrayList;
import java.util.Scanner;
import javax.naming.spi.DirStateFactory.Result;
public class Test06 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
int N = scanner.nextInt();
ArrayList<Integer> evens = new ArrayList<Integer>();//存放偶数
ArrayList<Integer> odds = new ArrayList<Integer>();//存放奇数
for (int i = 0; i < N; i++) {
int num=scanner.nextInt();
if(num%2==0){
evens.add(num);
}
odds.add(num);
}
//最大的素数对也就是跟奇数的个数相等,因为素数一定是一个偶数加一个奇数
int result=0;
int matched[]=new int[evens.size()];
for(int i=0;i<odds.size();i++){
int used []=new int[evens.size()];
if(find(odds.get(i),used,matched,evens)){
result++;
}
}
System.out.println(result);
}
scanner.close();
}
private static boolean find(Integer integer, int[] used, int[] matched,
ArrayList<Integer> evens) {
for(int j=0;j<evens.size();j++){
if(isPrim(integer, evens.get(j)) && used[j]==0){
used[j]=1;
if(matched[j]==0 || find(matched[j], used, matched, evens)){
matched[j]=integer;
return true;
}
}
}
return false;
}
public static boolean isPrim(int num1, int num2) {
int sum = num1 + num2;
for (int i = 2; i < sum; i++) {
if (sum % i == 0) {
return false;
}
}
return true;
}
}