本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。
欢迎大家订阅我的专栏:算法题解:C++与Python实现!
附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总
【题目来源】
AcWing:1118. 分成互质组 - AcWing题库
【题目描述】
给定 n n n 个正整数,将它们分组,使得每组中任意两个数互质。
至少要分成多少个组?
【输入】
第一行是一个正整数 n n n。
第二行是 n n n 个不大于 10000 10000 10000 的正整数。
【输出】
一个正整数,即最少需要的组数。
【输入样例】
6
14 20 33 117 143 175
【输出样例】
3
【算法标签】
《AcWing 1118 分成互质组》 #DFS#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 10; // 定义最大数字数量
int n; // 数字数量
int p[N]; // 存储所有数字
int group[N][N]; // 存储分组情况
bool st[N]; // 标记数字是否已被分组
int ans = N; // 记录最少分组数,初始化为最大值
/**
* 计算两个数的最大公约数
* @param a 第一个数
* @param b 第二个数
* @return 最大公约数
*/
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
/**
* 检查数字是否能加入当前分组
* @param group 当前分组中的数字索引数组
* @param gc 当前分组中的数字数量
* @param i 要检查的数字索引
* @return 是否可以加入分组
*/
bool check(int group[], int gc, int i)
{
for (int j = 0; j < gc; j++)
{
if (gcd(p[group[j]], p[i]) > 1)
{
return false;
}
}
return true;
}
/**
* 深度优先搜索函数,寻找最少分组数
* @param g 当前分组数
* @param gc 当前分组中的数字数量
* @param tc 已分组的总数字数量
* @param start 开始搜索的数字索引
*/
void dfs(int g, int gc, int tc, int start)
{
// 剪枝:如果当前分组数已超过已知最小分组数,直接返回
if (g >= ans)
{
return;
}
// 如果所有数字都已分组,更新最小分组数
if (tc == n)
{
ans = g;
}
bool flag = true; // 标记是否找到可以加入当前分组的数字
// 尝试将未分组的数字加入当前分组
for (int i = start; i < n; i++)
{
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; // 表示找到了可加入的数字
}
}
// 如果没有数字能加入当前分组,则创建新分组
if (flag)
{
dfs(g + 1, 0, tc, 0);
}
}
int main()
{
// 输入数字数量
cin >> n;
// 输入所有数字
for (int i = 0; i < n; i++)
{
cin >> p[i];
}
// 开始深度优先搜索
dfs(1, 0, 0, 0);
// 输出最少分组数
cout << ans << endl;
return 0;
}
【运行结果】
6
14 20 33 117 143 175
3