題目描述
題目描述
若兩個正整數的和爲素數,則這兩個正整數稱之爲“素數伴侶”,如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;
}
}