【回溯法】子集合问题

简介: 【回溯法】子集合问题

 一、题目描述:

【问题描述】子集和问题的一个实例为<S,M>。其中S={x1,x2,…,xn}是一个正整数的集合,M是一个正整数。找出S的所有子集S1,使得S1中所有元素的和为M。试设计一个解子集和问题的回溯法。

【样例输入】

5 10 12 13 15 18

30

【样例输出】

5 10 15

5 12 13

12 18

【样例说明】输入第一行是集合S,第二行是整数M;输出每一行代表一个解

二、设计思想

1、方法:递归+回溯

2、递归:back(i) 中含 back(i+1)

    回溯:不放第i元素,继续 back(i+1)

3、back(i)主体:

     (1)、if(i>n || Sum>SumFlag ||Num[i]>SumFlag) return; 跳出

     (2)、满足条件,打印

     (3)、放入第i元素,back(i+1)递归

                  Sum=Sum-Num[i];//回溯

                  不放入第i元素,back(i+1)递归

三、代码如下:

#include <bits/stdc++.h>
#define N 100000
using namespace std;
int n=6;//集合中元素个数
int Sum=0;//存目前计算的元素和 
int SumFlag=0;//SumFlag值为所需求的元素和
int Num[N];//集合的元素 
bool flag[N];//flag[i]=true表示放入计算,flag[i]=false表示未放入计算 
void back(int i){
  if(i>n || Sum>SumFlag ||Num[i]>SumFlag) return;//穷尽元素数组或者和大于SumFlag,跳出
  //数组存储有数据的i最大值为n-1,将其放入flag数组为一次操作
  //若其放入后,存储的元素满足题意,执行打印为一次操作使i=n
  //跳出为一次操作使i=n+1
  //所以此次判断为i>n,而不是i>n-1 
  else if(Sum==SumFlag){//满足条件,输出 
    for(int i=0;i<n;i++){
      if(flag[i]){
        cout<<Num[i]<<" ";
      }
    }
    cout<<endl;
  }
  else{
    Sum=Sum+Num[i];
    flag[i]=true;//第i元素加入满足条件的元素组 
    back(i+1);//递归  
    Sum=Sum-Num[i];//回溯 
    flag[i]=false;//第i元素不加入满足条件的元素组
    back(i+1);//递归   
  } 
}
int main(){   
  for(int i=0;i<n;i++){//输入元素值 
    cin>>Num[i];
    flag[i]=false;//将其对应的flag[i]设置为false 
  }
  cin>>SumFlag;//SumFlag值为所需求的元素和
  back(0);
  return 0;
}

image.gif

四、示例

1、示例输入:

5 10 12 13 15 18
30
image.gif

2、示例输出:

5 10 15
5 12 13
12 18
image.gif


目录
相关文章
|
算法 索引
回溯算法
回溯算法
65 0
|
7月前
|
机器学习/深度学习 人工智能 算法
回溯算法是怎样的
回溯算法,择优搜索:树的深搜+剪枝
|
8月前
|
算法 C++
回溯算法详解
回溯算法详解
110 0
|
机器学习/深度学习 算法 网络协议
回溯法
回溯法也可以叫做回溯搜索法,它是一种搜索的方式。 回溯是递归的副产品,只要有递归就会有回溯。 所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。 回溯法的效率 回溯法的性能如何呢,这里要和大家说清楚了,虽然回溯法很难,很不好理解,但是回溯法并不是什么高效的算法。 因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质。 那么既然回溯法并不高效为什么还要用它呢? 因为没得选,一些问题能暴力搜出来就不错了,撑死了再剪枝一下,还没有更高效的解法。 此时大家应该好奇了,都什么问题,这么牛逼,只能暴力搜索。 回溯法
|
人工智能 算法
【算法】回溯法的应用
回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。
258 0
|
算法
【算法】 八皇后问题之回溯法
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。每次填满第一行第一列,当不满足时候,试下第一行第二列,依次进行,递归的出口为找到第八个点,跳出递归。,在循环里面还要判断是否满足不同行,不同列,不同对角线。使用回溯法来解决该问题,下面的代码是我看到过的最精简的代码,相关的注释都写在代码上了。运行得出结果,总共有92中结果。
277 0
|
算法 Java
【递归与回溯算法】汉诺塔与八皇后问题详解
文章目录 1 汉诺塔问题 1.1 汉诺塔问题概述 1.2 思路分析 1.3 代码实现(Java) 1.4 结果验证 2 八皇后问题 2.1 八皇后问题概述 2.2 思路分析 2.2.1 问题划分与分析 2.2.2 涉及到的数据结构分析 2.2.3 上下对角线与行列的关系 2.3 代码实现(Java) 2.4 结果验证
【递归与回溯算法】汉诺塔与八皇后问题详解
一文学会回溯算法解题技巧
一文学会回溯算法解题技巧
追根溯源——回溯算法(二)
追根溯源——回溯算法(二)
追根溯源——回溯算法(二)