素数伴侣(二分图最大匹配问题&匈牙利算法)

题目描述

题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如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;
	}

}

 

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