素數伴侶(二分圖最大匹配問題&匈牙利算法)

題目描述

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

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章