题目描述
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
输入
第一行是一个正整数n。1 <= n <= 10。
第二行是n个不大于10000的正整数。
输出
一个正整数,即最少需要的组数。
样例输入
6 14 20 33 117 143 175
样例输出
3
题目解释
每次将当前组与其他数比较,是否被选过如果没选过,是否与当前组数是否都互质,如果互质就存下来并且进行下一层循环
如果找不到符合条件的就进行下一组并将当前数存入下一组
最后输出组数
程序实现
int gcd(int y,int x)
{
int r=x%y;
while(r)
{
x=y;
y=r;
r=x%y;
}
return y;
}
判断是否互质,图形证明欧几里得算法
对a,b两个数每次进行将b=a,a=b%a直到b%a==0这时就找到a,b最大公约数了
回归本题当a,b两个数的最大公约数为1时两个数就是互质
bool check(int x,int cnt)
{
for(int i=0;i<g[cnt].size();i++)
{
if(gcd(x,g[cnt][i])!=1)return false;
}
return true;
}
将当前选到的数与当前的组中数每个判断是否互质,如果互质则回true否则false
void dfs(int cnt,int sum)
{
if(cnt>=ans) return;
if(sum==n) ans=cnt;
int f=0;
for(int i=1;i<=n;i++)
{
if(flag[i]==0&&check(num[i],cnt))
{
flag[i]=1;
g[cnt].push_back(num[i]);
dfs(cnt,sum+1);
g[cnt].pop_back();
flag[i]=0;
f=1;
}
}
if(f==0) dfs(cnt+1,sum);
}
当cnt>=ans时就已经不是分组最少的分组互质数了就直接退出枚举
当sum==n时代表当前分的组数更小且已经分完就将更小值赋值给ans
f:存储是否有数与其互质的状态有则为1无则为0
cnt:存储当前的组数
sum:当前以分组的数的个数
遍历所有书判断是否已经取过并且是否与当前组中的所有数互质
如果满足条件则标记已经取过将当前数入组
后将继续搜索分组
分组后
为不影响其他分组需将其初始化将其踢出组去除标记
并且标记当前数已有能进组的数
全部遍历完判断当前数是否能有数与其进行继续分组
若没有数则就重开一组继续分组
main()
{
cin>>n;
ans=n;
for(int i=1;i<=n;i++)
cin>>num[i];
dfs(1,0);
cout<<ans;
return 0;
}
最后输出答案