题解 | #素数伴侣#
素数伴侣
https://www.nowcoder.com/practice/b9eae162e02f4f928eac37d7699b352e
import java.util.List; import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); ArrayList<Integer> evens = new ArrayList<Integer>(); ArrayList<Integer> odds = new ArrayList<Integer>(); for (int i = 0; i < n; i++) { int h = in.nextInt(); if (h % 2 == 0) { evens.add(h); } else { odds.add(h); } } findPrime(evens, odds); } private static void findPrime(ArrayList<Integer> evens, ArrayList<Integer> odds) { int[] oddPartner = new int[odds.size()]; // 记录被匹配给odds的 evens值 int count = 0; for (int i = 0; i < evens.size(); i++) { boolean[] bool = new boolean[odds.size()]; // 记录odds 是否被匹配,轮询避免死循环用 if (match(evens.get(i),bool,oddPartner,odds)) count++; } System.out.println(count); } private static boolean match(int even, boolean[] bool, int[] oddPartner,ArrayList<Integer> odds) { for (int j = 0; j < odds.size(); j++) { // 轮询找到匹配 if (isPrimePartner(even, odds.get(j))&&!bool[j]) {// 是素数伴侣该bool[]值做递归阻断用 bool[j] = true; if (oddPartner[j]==0 ||match(oddPartner[j],bool,oddPartner,odds)) { // 值为0代表没匹配则直接匹配;如果该odd已经匹配,但是能找到新的匹配 则让出位 // 用例: 2 5 6 13 8 17 oddPartner[j] = even; return true; } } } return false; } private static boolean isPrimePartner(int a, int b) { int c = a + b; if(c==1) return false; for (int i = 2; i <= Math.sqrt(c); i++) { if (c % i == 0) { return false; } } return true; } }
匈牙利算法
用例:
2 5
6 13
8 17
首先2和5配, 是素数,直接配对;
到6,发现6和5也能配,会让2再去找有没有其它可以配对的;结果发现2和17能配, 于是(6,5)(2,17);
到8, 发现8和5能配,但5已经和6配了,让6去找别的能配对的,找到13,发现能配, 于是(8,5)(6,13)(2,17)。