HJ28 素数伴侣
描述
题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如 2 和 5、6 和 13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有 4 个正整数:2,5,6,13,如果将 5 和 6 分为一组中只能得到一组“素数伴侣”,而将 2 和 5、6 和 13 编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
输入:
有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。
输出:
输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。
数据范围: 1≤n≤100 1≤n≤100 ,输入的数据大小满足 2≤val≤30000 2≤val≤30000
输入描述:
输入说明
1 输入一个正偶数 n
2 输入 n 个整数
输出描述:
求得的“最佳方案”组成“素数伴侣”的对数。
示例 1
输入:
4
2 5 6 13
输出:
2
示例 2
输入:
2
3 6
输出:
0
题解
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
// 输入N(N为偶数)个正整数,从其中挑选出若干对组成“素数伴侣”。
// 问怎么挑选,可以使得“素数伴侣”的对数最多。
// 如果两个正整数的和为素数,则这两个正整数称之为“素数伴侣”。
// 匈牙利算法
// 偶数(除去2)必定不是素数
// 奇数与偶数配对才可以得到奇数
// 即 奇数组 与 偶数组 配对 的最大匹配数
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt(); // 正偶数 表示待挑选的自然数的个数
// 输入n个整数
List<Integer> num1 = new ArrayList<>();// 奇数
List<Integer> num2 = new ArrayList<>();// 偶数
for (int i = 0; i < n; i++) {
int a = in.nextInt();
if (a % 2 == 0) {
//偶数
num2.add(a);
} else {
//奇数
num1.add(a);
}
}
getK(num1, num2);
}
}
public static void getK(List<Integer> list1, List<Integer> list2) {
// 两个正整数的和为素数,则这两个正整数称之为“素数伴侣”
// 寻找出“最佳方案”
// 素数伴侣对数
// 匈牙利算法 : 先到先得 能让就让
int [] match2 = new
int[list2.size()]; // 下表对应匹配的偶数的下表 值对应这个偶数的伴侣
int count = 0;// 记录对数
// 最佳方案
for (int i = 0; i < list1.size(); i++) {
// 标记对应的偶数是否查找过
boolean [] v = new boolean[list2.size()];
if (findMatch(list1.get(i), match2, list2, v)) {
count++;
}
}
System.out.println(count);
}
// 判断是否能够匹配到素数伴侣
public static boolean findMatch(int x, int [] match2, List<Integer> list,
boolean [] v) {
//
for (int i = 0; i < list.size(); i++) {
if (isPrime(x + list.get(i)) && v[i] == false) {
// 判断 是否为素数伴侣 且 该偶数未被匹配过
v[i] = true;
// 如果i位置偶数还没有伴侣,则与x组成伴侣,
//如果已经有伴侣,并且这个伴侣能重新找到新伴侣,则把原来伴侣让给别人,自己与x组成伴侣
if (match2[i] == 0 || findMatch(match2[i], match2, list, v)) {
match2[i] = x;
return true;
}
}
}
return false;
}
// 判断是否为素数(质数)
public static boolean isPrime(int a) {
boolean res = true;
for (int i = 2; i <= Math.sqrt(a); i++) {
if (a % i == 0) {
res = false;
break;
}
}
return res;
}
}