DFS之搜索顺序 AcWing 1118. 分成互质组
原题链接
算法标签
DFS
思路
1 数组划分
划分策略
优先选择将该数加至最后一组,若无法将该数加至最后-组,新开数组并将该数放置新开数组中
证明
代码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
#define ump unordered_map
#define pq priority_queue
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>b;--i)
using namespace std;
typedef pair<int, int> PII;
const int N = 10;
//int t, n, m, cnt, ans;
int n;
int p[N];
int group[N][N];
bool st[N];
//由于是求最小值,这里初始化为最大值
int ans=N;
inline int rd(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put(int x) {
if(x<0) putchar('-'),x=-x;
if(x>=10) put(x/10);
putchar(x%10^48);
}
// 判断下标为i的元素与数组g中元素是否互质
bool check(int g[], int gc, int i){
rep(j, 0, gc){
if(__gcd(p[g[j]], p[i])>1){
return false;
}
}
return true;
}
//当前需放置至哪个分组;要放在该分组的位置下标;当前已分组完毕的元素个数;从哪个位置开始选择元素【组合套路(定一个遍历顺序)】
void dfs(int g, int gc, int tc, int sta){
// 当前搜素组数 > 当前答案 则当前答案非最终答案 直接返回
if(g>=ans){
return;
}
// 已将所有元素分到互斥的组中 更新答案
if(tc==n){
ans=g;
}
//从start开始找,是否有元素不能放到g组中
bool flag=true;
rep(i, sta, n){
// 尚未搜素过且与当前组内元素互质
if(!st[i]&&check(group[g], gc, i)){
st[i]=true;
// 放入该数组
group[g][gc]=i;
// 递归搜索
dfs(g, gc+1, tc+1, i+1);
st[i]=false;
flag=false;
}
}
//新开一个分组
//由于dfs每层之间确定了顺序,所以期间存在元素被漏掉,【比如一开始你找的一串序列(1)是1,2,3,4 但是第二次(2)是1,2,4 很显然此时
//(2)还有一个3没有得到分组,需要从start=0开始把它找到!】
//因此当所有元素都不能放进当前分组的时候 或者 当start=n-1了但是元素没有全部分组完毕时,要重新从start=0开始找,并且一定要有st数组!!!不然会把一个元素重复的分组!(即恢复现场)
if(flag){
dfs(g+1, 0, tc, 0);
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
n=rd();
rep(i, 0, n){
p[i]=rd();
}
//通过g就得到当前分组数;由于ans初始化即为10,因此打算开第10个分组时,会被弹回,数组不会越界
dfs(1, 0, 0, 0);
printf("%lld\n", ans);
return 0;
}
参考文献
AcWing 1118. 分成互质组(算法提高课)y总视频讲解
原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈