牛客网:素数伴侣(二分图最大匹配)

题目描述

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

思路:不知道为什么题目给了个动态规划的标签(好吧,匈牙利还真有点动态规划的思想),真正解法藏的不深,相信熟悉二分匹配的人可以很容易看出这是一个匹配问题,我们可以将输入数据按照奇偶性构建二分图(两个偶数或者两个奇数肯定是不能相加得到素数的),之后直接跑匈牙利算法即可。

import javax.swing.*;
import java.beans.IntrospectionException;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.*;

public class Main {
    static int[] link;
    static int[] a, b, c;
    static int[][] edges;
    static boolean[] vis;

    private static void init() {
        a = new int[100005];
        a[0] = a[1] = 1;
        for (int i = 2; i < 100000; i++) {
            if (a[i] > 0)
                continue;
            for (long j = (long) i * i; j > 0 && j < 100000; j += i)
                a[(int) j] = 1;
        }
    }

    public static void main(String[] args) {
        init();
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {
            int n, ans = 0;
            n = in.nextInt();
            link = new int[n];
            vis = new boolean[n];
            edges = new int[n][n];
            int[] arr = new int[n];
            Arrays.fill(link, -1);
            for (int i = 0; i < n; i++)
                arr[i] = in.nextInt();
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++) {
                    if (i == j) continue;
                    if (a[arr[i] + arr[j]] == 0 && arr[i] % 2 != 0)
                        edges[i][j] = 1;
                }
            for (int i = 0; i < n; i++) {
                Arrays.fill(vis, false);
                if (dfs(i, n)) ans++;
            }
            System.out.println(ans);
        }
    }

    private static boolean dfs(int u, int n) {
        for (int i = 0; i < n; i++) {
            if (edges[u][i] == 0 || vis[i])
                continue;
            vis[i] = true;
            if (link[i] == -1 || dfs(link[i], n)) {
                link[i] = u;
                return true;
            }
        }
        return false;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值