【题目描述】
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
【题目链接】
http://noi.openjudge.cn/ch0205/7834/
【算法】
1、一开始以为要用二分,然后想了下,感觉判定分成n组是否有效,这个条件似乎帮不上什么忙。然后数据范围这么小,应该是贪心+暴力。感觉这个dfs有点不好写,而且是为了写dfs而写dfs。
2、a了之后,看了下网上其它题解。感觉思路比我要清晰的多的多:动态维护一个集合序列,对每一个数依次判断是否可以放入集合中,若可以则放入,若不行则新开一个集合放,然后感觉也不用dfs,于是写了个非递归版本。所以就算是贪心水题吧。。。
3、话说非递归真好调试啊。总结下,感觉是对数据处理方面的思考不够,动态维护集合的思想很关键。
4、第二个代码思路来自:https://blog.csdn.net/clove_unique/article/details/50239181,不过她是用bfs的,另看了她的oi退役,莫名有点感动,有点泪目。。。。想到自己高中三年的浑浑噩噩,和高三的不堪,往事依稀浑似梦 都随风雨到心头--
【代码1】
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct data{ int x,y; bool v; }a[20];// v表示是否已经在一个组中,x表示数,y表示是否在待选组中。y初始化为1表示所有数都是第一组的待选数,设置这个变量的目的是组中任两个数要两两互质,在不同栈中 4 int n,i,ans; //易于区分 5 bool gcd(int x,int y) 6 { 7 return (y?gcd(y,x%y):x)==1; 8 } 9 void dfs(int x) 10 { 11 a[x].v=1; 12 int rec=0,first=1,flag=0; 13 for(int i=x+1;i<=n;i++) { 14 if(a[i].y==a[x].y) { 15 if(gcd(a[i].x,a[x].x)) 16 if(first) rec=i,first=0; 17 else flag=1; 18 else 19 a[i].y++; 20 } 21 } 22 if(flag) dfs(rec); 23 else 24 for(int i=1;i<=n;i++) 25 if(a[i].y==a[x].y) a[i].v=1; 26 } 27 int main() 28 { 29 cin>>n; 30 for(i=1;i<=n;i++) cin>>a[i].x,a[i].y=1; 31 for(i=1;i<=n;i++) 32 if(!a[i].v) dfs(i),ans++; 33 cout<<ans; 34 return 0; 35 }
【代码2】
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,i,j,k; 4 int a[20][20],ans,tot[20],b[20]; 5 bool gcd(int x,int y) 6 { 7 return (y?gcd(y,x%y):x)==1; 8 } 9 int main() 10 { 11 cin>>n; 12 for(i=1;i<=n;i++) cin>>b[i]; 13 for(i=1;i<=n;i++) { 14 int flag=0; 15 for(j=1;j<=ans;j++) { 16 int cur=0; 17 for(k=1;k<=tot[j];k++) { 18 if(!gcd(b[i],a[j][k])) cur=1; 19 } 20 if(!cur) { a[j][++tot[j]]=b[i],flag=1,tot[j]++; break; } 21 } 22 if(!flag) a[++ans][1]=b[i],tot[ans]++; 23 } 24 cout<<ans; 25 return 0; 26 }