分配互质组
1.题目
输入N,和N个整数,求将这N个整数分成两两互质的组所需的组数。
(写个短题偷懒~)
2.思考:
两个数之间最大公约数为1即为互质。
那么,将数字当成节点,关系当成连接两个节点之间的边,将问题抽象成图。即如果两个数互质,那么对应两个节点有边相连。所以,按照顺序用dfs策略,判断考虑每一个数应该放到哪个组,可进入哪个组,相当于判断哪些节点相连,可走哪条路。
比如:设定组1为{2},组2为{3},那么数字4有三种选择,进入组1,进入组2,或者新建组3。则随机选择,进入组1发现组1数字2和数字4不互质,所以不可行,返。进入组2发现可行。则继续判断下一个数。
直到所有的数字都已经分配完毕则结束。
3.代码实现
#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n;//元素个数
int g[N];//存放题目所给出元素
int ans=0x3f; //最终答案,初始化答案为一个大数
int num=0;//目前组数
vector<int>v[N];//存放每一组的元素
void dfs(int x);
bool check(int val,int k){//检验val能否放入第k组
for(int i=0;i<v[k].size();i++){
if(__gcd(val,v[k][i])!=1)//__gcd(x,y)内置函数,返回x和y的最大公约数。如果最大公约数不为1,则互质
return false;
}
return true;
}
int main(){
cin>>n;//输入数据
for(int i=1;i<=n;i++)
cin>>g[i];
dfs(1);//从第一个数开始搜索
cout<<ans<<endl;//输出结果
return 0;
}
void dfs(int x){
if(x==n+1){//个数等于n+,即已经搜索完了最后一个数,遍历完毕
ans=min(num,ans);//更新组数得到答案
return;
}
int y=g[x];//获得x位置的值
for(int i=1;i<=num;i++){
if(check(y,i)){//判断是y否可以放入
v[i].push_back(y); //将y放入相应组i
dfs(x+1);//继续搜索
v[i].pop_back();//将数y丢出来,恢复现场
}
}
num++;//如果都不能放入,则新开一个数组
v[num].push_back(y);//放入y
dfs(x+1);
v[num].pop_back();//恢复现场
num--;
}