题目描述
题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如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
思路:不知道为什么题目给了个动态规划的标签(好吧,匈牙利还真有点动态规划的思想),真正解法藏的不深,相信熟悉二分匹配的人可以很容易看出这是一个匹配问题,我们可以将输入数据按照奇偶性构建二分图(两个偶数或者两个奇数肯定是不能相加得到素数的),之后直接跑匈牙利算法即可。
import javax.swing.*;
import java.beans.IntrospectionException;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;
public class Main {
static int[] link;
static int[] a, b, c;
static int[][] edges;
static boolean[] vis;
private static void init() {
a = new int[100005];
a[0] = a[1] = 1;
for (int i = 2; i < 100000; i++) {
if (a[i] > 0)
continue;
for (long j = (long) i * i; j > 0 && j < 100000; j += i)
a[(int) j] = 1;
}
}
public static void main(String[] args) {
init();
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n, ans = 0;
n = in.nextInt();
link = new int[n];
vis = new boolean[n];
edges = new int[n][n];
int[] arr = new int[n];
Arrays.fill(link, -1);
for (int i = 0; i < n; i++)
arr[i] = in.nextInt();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (i == j) continue;
if (a[arr[i] + arr[j]] == 0 && arr[i] % 2 != 0)
edges[i][j] = 1;
}
for (int i = 0; i < n; i++) {
Arrays.fill(vis, false);
if (dfs(i, n)) ans++;
}
System.out.println(ans);
}
}
private static boolean dfs(int u, int n) {
for (int i = 0; i < n; i++) {
if (edges[u][i] == 0 || vis[i])
continue;
vis[i] = true;
if (link[i] == -1 || dfs(link[i], n)) {
link[i] = u;
return true;
}
}
return false;
}
}