AcWing 1118. 分成互质组

原题链接

考察:玄学dfs

思路1:

       枚举组,判定当前数能否放进当前所有组.if 能, 加入到组中 else 新创立一个组.关键在于判定组内元素与当前数是否互质,这里用乘积代表组内的元素,如果与乘积不会互质,那么与组内所有元素一定不互质.(但是感觉会爆long long,10个数字,1040,但是实际测试没有爆)

       时间22ms

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N = 13,INF = 0x3f3f3f3f;
 8 int a[N],ans = INF,n;
 9 vector<LL> v;
10 int gcd(int a,int b)
11 {
12     return b?gcd(b,a%b):a;
13 }
14 void dfs(int x)
15 {
16     if(v.size()>=ans) return;
17     if(x>n)
18     {
19         ans = min(ans,(int)v.size());
20         return;
21     }
22     for(int i=0;i<v.size();i++)
23     {
24         if(gcd(a[x],v[i])==1)
25         {
26             v[i] = v[i]*a[x];
27             dfs(x+1);
28             v[i] = v[i]/a[x];
29         }
30     }
31     v.push_back(a[x]);
32     dfs(x+1);
33     v.pop_back();
34 }
35 int main()
36 {
37     scanf("%d",&n);
38     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
39     dfs(1);
40     printf("%d\n",ans);
41     return 0;
42 }
枚举组

思路2:

        对于当前组,枚举每一个能放进去的数.如果没有能放进去的数,说明我们要开一个新组.

        这种搜索可以搜到最优解.对于当前数x,假设它可以放入当前组C,但是设它放在新组能获得最优解.放完所有元素后,x能在新组中被拿出,再放入第C组,不影响最优解大小.

        这里需要两个剪枝: 如果当前枚举组数比最优解大 return,如果当前组可以放入元素,就不需要枚举它不放元素的情况.

        还有一个重要的优化是这里放组是组合型放入,也就是不是排列型枚举,可以用一个变量start规定按下标枚举.只放入比当前数字下标大的元素.

        这种搜索实际上枚举了每组从每个元素开始放的情况.有大佬在另开新组的地方优化为新租放第一个还未没分组的数,代码优化到40ms..

        时间700ms

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int N = 11;
 6 int a[N],n,g[N][N],ans = N;
 7 bool st[N];
 8 int gcd(int a,int b)
 9 {
10     return b?gcd(b,a%b):a;
11 }
12 bool check(int gr,int sz,int x)
13 {
14     for(int i=1;i<=sz;i++)
15       if(gcd(g[gr][i],x)>1) return 0;
16     return 1;
17 }
18 void dfs(int gr,int sz,int start,int tot)
19 {
20     if(gr>=ans) return;//最优性剪枝.
21     if(tot==n) {ans = gr;return;}
22     bool ok = 0;//如果能放元素就尽量不要放新组.
23     for(int i=start;i<=n;i++)
24     {
25         if(!st[i]&&check(gr,sz,a[i]))
26         {
27             st[i] = 1;
28             g[gr][sz+1] = a[i];
29             dfs(gr,sz+1,i+1,tot+1);
30             ok = 1;
31             st[i] = 0;
32         }
33     }
34     if(!ok) dfs(gr+1,0,1,tot);//枚举的组已经不能再放元素.
35 }
36 int main()
37 {
38     scanf("%d",&n);
39     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
40     dfs(1,0,1,0);
41     printf("%d\n",ans);
42     return 0;
43 }
枚举数

 

posted @ 2021-03-08 21:21  acmloser  阅读(97)  评论(0编辑  收藏  举报