素数伴侣-匈牙利算法

HJ28 素数伴侣

描述

题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如 2 和 5、6 和 13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有 4 个正整数:2,5,6,13,如果将 5 和 6 分为一组中只能得到一组“素数伴侣”,而将 2 和 5、6 和 13 编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。

输入:

有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。

输出:

输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。

数据范围: 1≤n≤100 1≤n≤100 ,输入的数据大小满足 2≤val≤30000 2≤val≤30000

输入描述:

输入说明
1 输入一个正偶数 n
2 输入 n 个整数

输出描述:

求得的“最佳方案”组成“素数伴侣”的对数。

示例 1

输入:
4
2 5 6 13
输出:
2

示例 2

输入:
2
3 6
输出:
0

题解

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

// 输入N(N为偶数)个正整数,从其中挑选出若干对组成“素数伴侣”。
// 问怎么挑选,可以使得“素数伴侣”的对数最多。
// 如果两个正整数的和为素数,则这两个正整数称之为“素数伴侣”。

// 匈牙利算法
// 偶数(除去2)必定不是素数
// 奇数与偶数配对才可以得到奇数
// 即 奇数组 与 偶数组 配对 的最大匹配数

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int n = in.nextInt(); // 正偶数 表示待挑选的自然数的个数
            // 输入n个整数
            List<Integer> num1 = new ArrayList<>();// 奇数
            List<Integer> num2 = new ArrayList<>();// 偶数
            for (int i = 0; i < n; i++) {
                int a = in.nextInt();
                if (a % 2 == 0) {
                    //偶数
                    num2.add(a);
                } else {
                    //奇数
                    num1.add(a);
                }
            }
            getK(num1, num2);
        }
    }

    public static void getK(List<Integer> list1, List<Integer> list2) {
        // 两个正整数的和为素数,则这两个正整数称之为“素数伴侣”
        // 寻找出“最佳方案”
        // 素数伴侣对数
        // 匈牙利算法 : 先到先得 能让就让
        int [] match2 = new
        int[list2.size()]; // 下表对应匹配的偶数的下表 值对应这个偶数的伴侣
        int count = 0;// 记录对数
        // 最佳方案
        for (int i = 0; i < list1.size(); i++) {
            // 标记对应的偶数是否查找过
            boolean [] v = new boolean[list2.size()];
            if (findMatch(list1.get(i), match2, list2, v)) {
                count++;
            }
        }
        System.out.println(count);
    }
    // 判断是否能够匹配到素数伴侣
    public static boolean findMatch(int x, int [] match2, List<Integer> list,
                                    boolean [] v) {
        //
        for (int i = 0; i < list.size(); i++) {
            if (isPrime(x + list.get(i)) && v[i] == false) {
                // 判断 是否为素数伴侣 且 该偶数未被匹配过
                v[i] = true;
                // 如果i位置偶数还没有伴侣,则与x组成伴侣,
                //如果已经有伴侣,并且这个伴侣能重新找到新伴侣,则把原来伴侣让给别人,自己与x组成伴侣
                if (match2[i] == 0 || findMatch(match2[i], match2, list, v)) {
                    match2[i] = x;
                    return true;
                }
            }
        }
        return false;
    }
    // 判断是否为素数(质数)
    public static boolean isPrime(int a) {
        boolean res = true;
        for (int i = 2; i <= Math.sqrt(a); i++) {
            if (a % i == 0) {
                res = false;
                break;
            }
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值