这一题直接用的暴力搜索,考虑优化的话可以学习一下最大团算法来进行优化
AC代码:
#include <iostream>
using namespace std;
int n;
int p[N]; // 存数
int group[N][N]; // 最多可能有N个组, 每个组可能有N个数 存的是数的序号(保证可以连续性访问)
bool st[N];
int res = N; // 组数的最大值是n个数两两互质
int gcd (int a, int b)
{
return b ? gcd(b, a % b) : a;
}
bool check (int u, int v, int i)
{
for(int j = 0 ; j < v ; j ++ )
if(gcd(p[group[u][j]], p[i]) > 1) return 0;
return 1;
}
/*
u -> 第几组
v -> 第几组中的第几个数
w -> n个数我用了多少个数
x -> 当前从哪个序列编号开始找下一个互质的数放入组中
*/
void dfs(int u, int v, int w, int x) // 递归指数型枚举
{
if(u >= res) return ;
if(w == n)
{
res = u;
return ; // 终点时刻要不要这个return都可以
}
/*
页首的样例不加flag会T(还是可以跑出正确答案但是要慢6倍左右)
因为不加flag的话在回溯的过程中会多回溯很多次第86行(本来不需要回溯的)
*/
bool flag = 1;
for(int i = x ; i < n ; i ++ )
if(!st[i] && check(u, v, i))
{
group[u][v] = i;
st[i] = 1;
flag = 0;
dfs(u, v + 1, w + 1, i + 1);
st[i] = 0;
}
if(flag) dfs(u + 1, 0, w, 0);
// 1. w不变因为我i还没有放进去 2. x == 0因为开辟一个新的组之后我们又从头开始找数了
}
int main ()
{
cin >> n;
for(int i = 0 ; i < n ; i ++ ) cin >> p[i];
dfs(1, 0, 0, 0);
cout << res << endl;
return 0;
}