子集树算法文档

1.算法概述

子集树是一种 回溯算法,用于生成一个集合的所有子集。给定一个数组 arr,该算法递归地遍历所有可能的子集,并通过一个辅助数组 x 标记当前元素是否被选中。

2.算法特点

  • 时间复杂度:O(2n)(因为一个包含 n 个元素的集合有 2n 个子集)。

  • 空间复杂度:O(n)(递归栈深度)。

  • 适用场景:需要枚举所有子集的问题,如组合、子集和、幂集等。

3.代码实现

#include <iostream>
#include <string>

using namespace std;
void func(int arr[], int i, int length,int x[])
{
    if (i == length)//递归终止条件:处理完所有元素
    {
        for (int j = 0; j < length; j++)
        {
            if (x[j] == 1)//如果当前元素被选中,则输出
                cout << arr[j] << " ";
        }
        cout << endl;
    }
    else
    {
        x[i] = 1;//选择当前节点
        func(arr, i + 1, length,x);//处理左子树
        x[i] = 0;//不选择当前节点
        func(arr, i + 1, length,x);//处理右子树
    }
}
int main()
{
    int arr[] = { 1,2,3 };
    int length = sizeof(arr) / sizeof(int);
    int x[3] = { 0 };//初始化数组为0
    func(arr, 0, length,x);
    return 0;
}

   在此列一道题目:在给出序列中,求所选元素和  与 未选元素和的最小差值是多少


#include <iostream>  
#include <cmath>    

using namespace std; 

// 定义全局变量
int arr[] = { 12, 6, 7, 11, 16, 3, 9 };  // 输入的数字数组
const int length = sizeof(arr) / sizeof(int);  // 计算数组长度

int x[length] = { 0 };   // 记录当前选择的元素(1表示选中,0表示未选中)
int sum = 0;           // 记录当前已选元素的和
int r = 0;             // 记录当前未选元素的和
int Min = 0x7FFFFFFF;  // 记录最小差值,初始设为最大整数值
int bestx[length] = { 0 };  // 记录最佳选择方案

// 回溯函数
void func(int i) {
    // 递归终止条件:已处理完所有元素
    if (i == length) {
        // 计算当前选择与未选择子集和的绝对差值
        int result = abs(sum - r);

        // 如果找到更小的差值,更新最优解
        if (result < Min) {
            Min = result;  // 更新最小差值
            // 保存当前最佳选择方案
            for (int j = 0; j < length; j++) {
                bestx[j] = x[j];
            }
        }
    }
    else {
        // 选择当前元素arr[i]的情况
        r -= arr[i];      // 从未选和中减去当前元素
        sum += arr[i];    // 将当前元素加到已选和
        x[i] = 1;         // 标记当前元素为已选
        func(i + 1);      // 递归处理下一个元素

        // 不选择当前元素arr[i]的情况
        sum -= arr[i];    // 从已选和中减去当前元素
        r += arr[i];      // 将当前元素加到未选和
        x[i] = 0;         // 标记当前元素为未选
        func(i + 1);      // 递归处理下一个元素
    }
}

int main() {
    // 计算数组所有元素的总和,初始化未选和r
    for (int v : arr) {
        r += v;
    }

    // 从第0个元素开始回溯搜索
    func(0);

    // 输出结果
    cout << "Selected: ";
    // 输出被选中的元素
    for (int i = 0; i < length; i++) {
        if (bestx[i]) {
            cout << arr[i] << " ";
        }
    }
    // 输出最小差值
    cout << "\nMin difference: " << Min << endl;

    return 0; 
}
 

继续列一道题:给出2n个整数,从里面挑选n个整数,使其让选择的整数的和  与未选择的整数的和的差值最小

#include <iostream> 
#include <cmath>     
#include <vector>   

// 定义全局变量
int arr[] = {12,6,7,11,16,3,8,9};           // 输入的数字数组
const int length = sizeof(arr)/sizeof(int); // 计算数组长度
std::vector<int> x;                         // 当前选择的元素集合(存储元素值)
std::vector<int> bestx;                     // 最佳选择的元素集合
int sum;                                    // 当前已选元素的和
int Left = length;                         // 剩余未处理的元素个数(初始为总长度)
int r;                                     // 当前未选元素的和
unsigned int Min = INT_MAX;               // 记录最小差值(初始为最大整数值)
int cnt;                                  // 记录递归调用次数(调试用)

// 回溯函数(i表示当前处理元素的索引)
void func(int i) {
    // 递归终止条件:已处理完所有元素
    if (i == length) {
        cnt++; // 递归次数统计
        
        // 检查是否恰好选中一半元素
        if (x.size() != length/2) return;
        
        // 计算当前差值
        int result = abs(sum - r);
        
        // 更新最优解
        if (result < Min) {
            Min = result;    // 更新最小差值
            bestx = x;       // 深拷贝当前选择路径
        }
        return;
    }
    // 未处理完所有元素时的递归操作
    else {
        Left--; // 减少剩余未处理元素数量
        
        // 分支1:选择当前元素(需满足选择数量未过半)
        if (x.size() < length/2) { // 剪枝条件1:已选数量不能超过半数
            // 选择当前元素
            sum += arr[i];   // 更新已选和
            r -= arr[i];     // 更新未选和
            x.push_back(arr[i]); // 记录选择路径
            
            func(i+1); // 递归处理下一个元素
            
            // 回溯操作
            sum -= arr[i];   // 恢复已选和
            r += arr[i];     // 恢复未选和
            x.pop_back();    // 移除当前选择
        }
        
        // 分支2:不选择当前元素(需满足剩余元素足够凑够半数)
        if (x.size() + Left >= length/2) { // 剪枝条件2:剩余元素足够完成选择
            func(i+1); // 递归处理下一个元素
        }
        
        Left++; // 恢复剩余未处理元素数量
    }
}

int main() {
    // 初始化未选和(总和)
    for(int num : arr) {
        r += num;
    }
    
    func(0); // 从第0个元素开始回溯
    
    // 输出结果
    std::cout << "Selected elements: ";
    for(int v : bestx) {
        std::cout << v << " ";
    }
    std::cout << "\nMinimum difference: " << Min << std::endl;
    std::cout << "Total recursions: " << cnt << std::endl; 
    
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80466.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTP/1.1 host虚拟主机详解

一、核心需求&#xff1a;为什么需要虚拟主机&#xff1f; 在互联网上&#xff0c;我们常常希望在一台物理服务器&#xff08;它通常只有一个公网 IP 地址&#xff09;上运行多个独立的网站&#xff0c;每个网站都有自己独特的域名&#xff08;例如 www.a-site.com​, www.b-s…

amass:深入攻击面映射和资产发现工具!全参数详细教程!Kali Linux教程!

简介 OWASP Amass 项目使用开源信息收集和主动侦察技术执行攻击面网络映射和外部资产发现。 此软件包包含一个工具&#xff0c;可帮助信息安全专业人员使用开源信息收集和主动侦察技术执行攻击面网络映射并执行外部资产发现。 使用的信息收集技术 技术数据来源APIs&#xf…

Spring Web MVC响应

返回静态页面 第一步 创建html时&#xff0c;要注意创建的路径&#xff0c;要在static下面 第二步 把需要写的内容写到body内 第三步 直接访问路径就可以 返回数据ResponseBody RestController Controller ResponseBody Controller&#xff1a;返回视图 ResponseBody&…

‌鸿蒙PC正式发布:国产操作系统实现全场景生态突破

鸿蒙PC正式发布&#xff1a;国产操作系统实现全场景生态突破‌ 2025年5月8日&#xff0c;华为在深圳举办发布会&#xff0c;正式推出搭载鸿蒙操作系统的个人电脑&#xff08;PC&#xff09;&#xff0c;标志着国产操作系统在核心技术与生态布局上实现历史性跨越。此次发布的鸿蒙…

【计算机视觉】OpenCV实战项目:Text-Extraction-Table-Image:基于OpenCV与OCR的表格图像文本提取系统深度解析

Text-Extraction-Table-Image&#xff1a;基于OpenCV与OCR的表格图像文本提取系统深度解析 1. 项目概述2. 技术原理与算法设计2.1 图像预处理流水线2.2 表格结构检测算法2.3 OCR优化策略 3. 实战部署指南3.1 环境配置3.2 核心代码解析3.3 执行流程示例 4. 常见问题与解决方案4.…

Redis BigKey 问题是什么

BigKey 问题是什么 BigKey 的具体表现是 redis 中的 key 对应的 value 很大&#xff0c;占用的 redis 空间比较大&#xff0c;本质上是大 value 问题。 BigKey怎么找 redis-cli --bigkeysscanBig Key 产生的原因 1.redis数据结构使用不恰当 2.未及时清理垃圾数据 3.对业务预…

go-gin

前置 gin是go的一个web框架&#xff0c;我们简单介绍一下gin的使用 导入gin &#xff1a;"github.com/gin-gonic/gin" 我们使用import导入gin的包 简单示例&#xff1a; package mainimport ("github.com/gin-gonic/gin" )func main() {r : gin.Default(…

C# NX二次开发:判断两个体是否干涉和获取系统日志的UFUN函数

大家好&#xff0c;今天要讲关于如何判断两个体是否干涉和获取系统日志的UFUN函数。 &#xff08;1&#xff09;UF_MODL_check_interference&#xff1a;这个函数的定义为根据单个目标体检查每个指定的工具体是否有干扰。 Defined in: uf_modl.h Overview Checks each sp…

如何解决 Linux 系统文件描述符耗尽的问题

在Linux系统中&#xff0c;文件描述符&#xff08;File Descriptor, FD&#xff09;是操作系统管理打开文件、套接字、管道等资源的抽象标识。当进程或系统耗尽文件描述符时&#xff0c;会导致服务崩溃、连接失败等严重问题。以下是详细的排查和解决方案&#xff1a; --- ###…

LVGL简易计算器实战

文章目录 &#x1f4c1; 文件结构建议&#x1f539; eval.h 表达式求值头文件&#x1f539; eval.c 表达式求值实现文件&#xff08;带详细注释&#xff09;&#x1f539; ui.h 界面头文件&#x1f539; ui.c 界面实现文件&#x1f539; main.c 主函数入口✅ 总结 项目效果&…

使用countDownLatch导致的线程安全问题,线程不安全的List-ArrayList,线程安全的List-CopyOnWriteArrayList

示例代码 package com.example.demo.service;import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class UnSafeCDTest {Executor…

ALLinSSL:一站式SSL证书管理解决方案

引言 在当今互联网安全日益重要的背景下,SSL证书已成为保护网站安全的必备工具。然而,管理多个SSL证书常常是一项繁琐且容易出错的任务。ALLinSSL应运而生,它提供了一个一站式的SSL证书管理解决方案,大大简化了证书的申请、安装和更新过程。本文将深入介绍ALLinSSL的特性、…

嵌入式通信协议总览篇:万物互联的基石

嵌入式系统的世界,是靠协议“说话”的世界。 在你设计一个智能设备、构建一个工业控制系统、开发一款 IoT 网关时,一个核心问题始终绕不开:**这些设备之间如何“对话”?**答案就是——通信协议。 本篇作为系列第一章,将带你全面理解嵌入式通信协议的全貌,为后续深入学习…

【数据结构】红黑树(C++)

目录 一、红黑树的概念 二、红黑树的性质 三、红黑树结点定义 四、红黑树的操作 1. 插入操作 1.1 插入过程 1.2 调整过程 1.2.1 叔叔节点存在且为红色 1.2.2 叔叔节点存在且为黑色 1.2.3 叔叔节点不存在 2. 查找操作 2.1 查找逻辑 2.2 算法流程图 2.3 使用示例 …

Oracle数据库DBF文件收缩

这两天新部署了一套系统&#xff0c;数据库结构保持不变&#xff0c;牵扯导出表结构还有函数&#xff0c;图省事就直接新建用户&#xff0c;还原数据库了。然后咔咔咔&#xff0c;一顿删除delete&#xff0c;truncate&#xff0c;发现要不就是表删了&#xff0c;还有num_rows&a…

【字节拥抱开源】字节豆包团队开源首发 Seed-Coder 大模型

我们非常高兴地向大家介绍 Seed-Coder&#xff0c;它是一个功能强大、透明、参数高效的 8B 级开源代码模型系列&#xff0c;包括基础变体、指导变体和推理变体。Seed-Coder 通过以下亮点促进开放代码模型的发展。 以模型为中心&#xff1a;Seed-Coder主要利用大语言模型&#…

Qt 无边框窗口,支持贴边分屏

常规操作, 无法进行窗口的大小缩放和移动贴边分屏等操作 // 去掉标题栏,去掉工具栏&#xff0c;窗口置顶 setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);重点介绍 QWindowKit https://github.com/stdware/qwindowkit 跨平台的支持Windows\…

Qt 样式表:全面解析与应用指南

在 Qt 开发中,样式表(Style Sheets)是定义应用程序界面外观的关键工具。它采用文本格式的规则集合,借鉴了 CSS 语法,借助选择器、属性和值,能精准把控各类控件的外观表现,极大提升了界面设计的灵活性与美观性。 文章目录 一、样式可更改的效果​1、颜色相关效果​2、字体…

追踪大型语言模型的思想(上)(来自针对Claude的分析)

概述 像 Claude 这样的语言模型并非由人类直接编程&#xff0c;而是通过大量数据进行训练。在训练过程中&#xff0c;它们会学习解决问题的策略。这些策略被编码在模型为每个单词执行的数十亿次计算中。对于我们这些模型开发者来说&#xff0c;这些策略是难以捉摸的。这意…