素数伴侣
算法知识视频讲解
困难 通过率:23.97% 时间限制:1秒 空间限制:32M
知识点
查找
排序
题目
题解(10)
讨论(111)
排行
warning 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。
描述
题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如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
3 6
复制
输出:
2
0

#if 0
#include <iostream>
#include <math.h>
#include <vector>
#include <algorithm>

using namespace std;

/* 素数:大于1的质数,即只能被1和它本身整除 */
bool primeNums(int first, int second) 
{
    int sum = first + second;
    bool flag = true;
    if(sum == 1 || sum == 2) {
        return false;
    } 
    //sqrt是开平方的函数,举个简单的例子:sqrt(4) = 2; sqrt(9) = 3;
    for(int i = 2; i <= sqrt(sum); i++) { 
        if(sum % i == 0) { //非素数
            flag = false;
            break;
        }
    }
    return flag;
}

/*
* 递归排列查找素数伴侣
* 思想:对输入的数组进行排序,对2个数据为一对数据相加的和是否为素数,若为素数,则素数伴侣个数count加1,
*     如果素数伴侣最大值maxx小于count,则count赋值于maxx;对数组进行递归排序
* 步骤:
* 第一步:输入数组个数和数组值
* 第二步:对数组进行排序sort
* 第三步:遍历查找一对数据的和是否为素数伴侣,若为素数,则素数伴侣个数count加1; 
      如果素数伴侣最大值maxx小于count,则count赋值于maxx;
      循环对数组进行递归排序next_permutation
*/
int maxPrimeMate(int *inputVec, int num)
{
    int maxValue = 0;
    sort(inputVec, inputVec+num);
    do {
        int count = 0;
        for(int i = 0; i < num; i+=2) {
            if(primeNums(inputVec[i], inputVec[i+1])) {
                count++;
            }
        }

        if(maxValue < count) {
            maxValue = count;
        }

    } while(next_permutation(inputVec, inputVec+num));
    return maxValue;
}
int main()
{
    int num;
    while(cin>>num) {
        int maxValue = 0;
        int *inputVec = new int[num];
        for(int i = 0; i < num; i++) {
            cin>>inputVec[i];
        }

        if(num % 2 == 0) {
            maxValue = maxPrimeMate(inputVec, num);
            cout<<maxValue<<endl;
        } else {
            cout<<maxValue<<endl;
        }
        delete inputVec;
    }
    return 0;
}


#else
#include <bits/stdc++.h>
using namespace std;
//判断一个数是否为素数
bool IsPrimer(int sum)
{
    bool flag = true;
    if(sum == 1 || sum == 2) {
        return false;
    } 
    //sqrt是开平方的函数,举个简单的例子:sqrt(4) = 2; sqrt(9) = 3;
    for(int i = 2; i <= sqrt(sum); i++) { 
        if(sum % i == 0) { //非素数
            flag = false;
            break;
        }
    }
    return flag;
}
//匈牙利算法,为某一个目标奇数找到它的素数伴侣(偶数),皆以下标表示
bool FindMate(const int& n, vector<vector<bool>>& map, vector<int>& match, vector<bool> &vis)
{
    for (int i = 0; i < match.size(); i++)
    {
        if (!vis[i] && map[i][n])//偶数未被访问过并且能与目标奇数组成素数(有关系)
        {
            vis[i] = true;
            if (match[i] == -1 || FindMate(match[i], map, match, vis))//当前偶数没有匹配或能给被抛弃的奇数找到新的偶数
            {
                match[i] = n;//找到这个偶数
                return true;
            }
        }
    }
    return false;
}

int main()
{
    int num = 0;
    while (cin >> num)
    {
        int count = 0;//匹配对数
        vector<int> even;//偶数
        vector<int> odd;//奇数
        int val = 0;
        //读取数据
        for (int i = 0; i< num; i++)
        {
            cin >> val;
            if (val % 2 == 0) { //偶数
                even.push_back(val);
            } else { //奇数
                odd.push_back(val);
            }
        }
        if (odd.empty() || even.empty())
        {
            cout << count << endl;
            continue;
        }
        //建立关系表,图中的边
        vector<vector<bool>> map(even.size(), vector<bool>(odd.size(), false));
        for (int i = 0; i < even.size(); i++)
        {
            for (int j = 0; j < odd.size(); j++)
            {
                if (IsPrimer(even[i] + odd[j])) //对素数进行判断
                {
                    map[i][j] = true;
                }
            }
        }

        if(num % 2 == 0) {
            //建立初始匹配表
            vector<int> match(even.size(), -1);   
            //为每一个奇数都尝试去找对应的偶数,   
            for (int i = 0; i < odd.size(); i++)
            {
                vector<bool> vis(even.size(), false);//每一次查找都相当于重新分配,标志要清零
                if (FindMate(i, map, match, vis))
                {
                    count++;
                }
            }
            cout << count << endl;
        } else {
            cout << count << endl;
        }


    }
}

#endif