IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> AcWing 1118. 分成互质组 -> 正文阅读

[数据结构与算法]AcWing 1118. 分成互质组

在这里插入图片描述
在这里插入图片描述
题意:

给定 n 个正整数,将它们分组,使得每组中任意两个数互质。

问:至少要分成多少个组?

思路:

dfs,对每一个元素,我们有两种操作

  • ①:放到现有组中的最后一组中(依次枚举最后一组的所有元素,判断新加的元素是否与它们全部互质,如果是的则加入)
  • ②:新开一个组并放入

p[N]存放n个元素
二维数组group[N][N]存放每个组

我们从第一个组 g=1,组内没有数 gc=0,当前用掉了 cnt=0 个元素,当前组还未开始遍历数 start=0 的初始状态开始搜索。

每次搜索的时候判断是否可以将元素放到现有组中的最后一组(用标记变量ok),如果不行再新开一组。

空白代码:

#include<bits/stdc++.h>

using namespace std;
const int N = 15;
int group[N][N], p[N];
bool st[N];
int n;
int ans;

int gcd(int a, int b)
{
    return b ? gcd(b, a%b) : a;
}

bool check(int g[], int gc, int a){
    for(int i=0;i<gc;++i)
    {
        if(gcd(g[i], a)!=1) return false;
    }
    return true;
}

void dfs(int g, int gc, int cnt, int start)
{
    if(g>=ans) return ;
    if(cnt==n) {ans = g; return ;}
    
    bool ok = false;
    for(int i=start; i<n; ++i)
    {
        if(!st[i]&&check(group[g], gc, p[i]))
        {
            st[i] = true;
            group[g][gc] = p[i];
            dfs(g, gc+1, cnt+1, i+1);
            st[i] = false;
            ok = true;
        }
    }
    if(!ok) dfs(g+1, 0, cnt, 0);
}

int main()
{
    cin>>n;
    for(int i=0;i<n;++i) cin>>p[i];
    ans = n;
    dfs(1, 0, 0, 0);
    cout<<ans<<endl;
    
    return 0;
}

代码 + 注释:

#include<bits/stdc++.h>
using namespace std;

const int N = 15;

int n;
int p[N];//存放n个元素
int group[N][N];//存放每个组
bool st[N];
int ans;

int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}

bool check(int g[], int gc, int a){//判断当前组中的数是否和该数都互质(即该数能否放进该组)
    for(int i=0;i<gc;++i)//枚举此组组内每个数
    {
        if(gcd(g[i], a)!=1) return false;//只要组内有数和该数不互质了就return false
    }
    return true;//否则return true
}

void dfs(int g, int gc, int cnt, int start)
{
    //g为当前的最后一组的组的序号,gc为当前组内 搜索到的 数的序号
    //cnt为当前 搜索过的 元素数量,start为当前组 开始搜索的 数(p数组中的元素)的序号

    if (g >= ans) return;//如果有比当前最优解所需的组数更多的解法说明此解不为最优解-->直接return即可
    if (cnt == n) {ans = g; return ;}//如果搜完了所有点了,说明此解为当前的最优解,更新最优解
    
    bool ok = false;//flag标记是否能新开一组
    for (int i = start; i < n; ++i)//枚举每个数
        if (!st[i] && check(group[g], gc, p[i]))//如果当前数还未被放进组里 且 与当前的组中的数都互质
        {
            st[i] = true;
            group[g][gc] = p[i];
            //分支一:继续搜索该组,组内数的数量gc + 1,总的数的数量cnt + 1,搜索的数的序号i + 1(组合型枚举,人为规定一个递增的顺序)
            dfs(g, gc + 1, cnt + 1, i + 1);
            st[i] = false;
            ok = true;//如果能放进当前最后一组,则不用新开一组,ok标记为true
        }
        
    //分支二 经过for的枚举后发现无法放进最后一组,ok没有发生什么变化,还是false,则新开一组来搜索
    if (!ok) dfs(g + 1, 0, cnt, 0);
    //当前最后一组的组的序号g + 1, 组内搜索的数的序号gc为0
    //搜索到的数cnt未变, 当前组内开始搜索的数的序号start为0(仍重新从0开始搜,放不放入新开的组内就看是否满足条件了)
}

int main()
{
    cin >> n;
    ans = n;//还未搜索时,假定最优解为最坏的情况每个数都分一组
    for (int i = 0; i < n; ++i) cin >> p[i];
    dfs(1, 0, 0, 0);
    //从第一个组 g=1, 组内没有数 gc=0
    //当前用掉了 cnt=0 个元素, 当前组还未开始遍历数 start=0 的初始状态开始搜索
    
    cout << ans << endl;
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 13:22:01  更:2022-03-06 13:26:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:31:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码