题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的N(N为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
输入:
有一个正偶数N(N≤100),表示待挑选的自然数的个数。后面给出具体的数字,范围为[2,30000]。
输出:
输出一个整数K,表示你求得的“最佳方案”组成“素数伴侣”的对数。
方法一:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
//二分图匹配,匈牙利算法
vector<int> evenArr, oddArr;
int match[101];
int book[101];
bool IsPrime(int n)
{
int n_sqrt = sqrt(n);
for(size_t i = 2; i <= n_sqrt; i++)
if(n%i == 0)
return false;
return true;
}
bool dfs(int u)//深度优先搜索
{
for(int i = 0; i < oddArr.size(); i++)
{
if(book[i] == 0 && IsPrime(evenArr[u] + oddArr[i]))
{
book[i] = 1;//标记点i已经访问过
//如果点i未被配对或者找到了新的配对
if(match[i] == -1 || dfs(match[i]))
{
//更新配对关系;
match[i] = u;
return true;
}
}
}
return false;
}
int main()
{
int n;
while(cin>>n)
{
int ele, sum = 0;
for(int i = 0; i < n; i++)
{
cin >> ele;
if(ele % 2 == 0)
evenArr.push_back(ele);//偶数
else
oddArr.push_back(ele);//奇数
}
for(int i = 0; i < n; i++)
match[i] = -1;
for(int i = 0; i < evenArr.size(); i++)
{
for(int j = 0; j < oddArr.size(); j++)
book[j] = 0;//清空上次搜索时的标记
if(dfs(i))
sum++;//寻找增广路径,如果找到,配对数加1
}
cout << sum << endl;
evenArr.clear();
oddArr.clear();
}
return 0;
}
方法二:
#include <iostream>
#include <vector>
#include<cmath>
using namespace std;
vector<int> cx(100, -1);
vector<int> cy(100, -1);
vector<int> visit(100, 0);
int t[100][100] = { 0 };
//判断是否是素数
bool isprime(int n)
{
int m = sqrt(n);
int flag = 0;
for (int i = 2; i <= m; i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
//寻找增广路径
int dfs(int u)
{
for(int i = 0; i < cx.size();i++)
{
if (t[u][i] && !visit[i])
{
visit[i] = 1;
if (cy[i] == -1 || dfs(cy[i])) ////
{
cx[u] = i; ////
cy[i] = u;
return 1;
}
}
}
return 0;
}
int main()
{
int N;
vector<int> cj;
vector<int> co;
while (cin >> N)
{
int tmp;
int ans = 0;
for (int i = 0; i < N; i++)
{
cin >> tmp;
if (tmp % 2 != 0)
cj.push_back(tmp);
else
co.push_back(tmp);
}
for (int i = 0; i < cj.size(); i++)
for (int j = 0; j <co.size(); j++)
{
if (isprime(cj[i] + co[j]))
t[i][j] = 1;
}
//匈牙利算法
for (int i = 0; i < cj.size(); i++)
{
if(cx[i] == -1)
{
for(int j = 0; j < visit.size();j++)
visit[j] = 0;
ans += dfs(i);
}
}
cout << ans << endl;
for(int i = 0; i < 100;i++)
for(int j = 0; j < 100;j++)
t[i][j] = 0;
for(int i =0; i < 100;i++)
cx[i] = cy[i] = -1;
cj.clear();
co.clear();
}
return 0;
}