入门算法-穷举法(计算完全数和求解幂集问题)

写在前面,关于穷举法的定义自行去Google,在我的理解就是暴力求解,把所有可能都推算出来,这对于自己没有其他策略和解题思路的情况下,可以使用穷举法,但是其弊端也是很明显的,相对于其他算法思想来说时间复杂度是极高的,所以慎用。

一、使用技术

蛮力法所赖的基本技术——扫描技术
基本的扫描技术——遍历
(1)集合的遍历:按集合中元素序号的顺序处理各元素
(2)线性表的遍历:以数组形式存储,按下标顺序处理
(3)树的遍历:对二叉树,包括前序、中序、后序和层序
(4)图的遍历:深度优先、广度优先

二、适用范围

(1)理论上,蛮力法可以解决可计算领域的各种问题。
(2)蛮力法经常用来解决一些较小规模的问题。
(3)对于某些问题,蛮力法可以产生一些合理的算法,他们具备一定实用价值,而且不受问题规模的限制。
(4)蛮力法可以作为某类问题时间性能的底限,作为衡量同样问题效率的基础算法。

三、求解过程

根据问题中的条件将可能的情况一一列举出来,逐一尝试从中找出满足问题条件的解。但有时列举的情况数目很大,则需要排除一些明显不合理的情况,以减少问题可能解规模。
用蛮力法解决问题,通常从两个方面进行算法设计:
1)找出枚举范围:分析问题所涉及的各种情况。
2)找出约束条件:分析问题的解需要满足的条件,并用逻辑表达式表示。

四、基本格式

在这里插入图片描述

五、例题

1、编写一个程序,输出2~1000之间的所有完全数。所谓完全数,是指这样的数,该数的各因子(除该数本身外)之和正好等于该数本身,例如:
  6=1+2+3
  28=1+2+4+7+14
解:先考虑对于一个整数m,如何判断它是否为完全数。从数学知识可知:一个数m的除该数本身外的所有因子都在1~m/2之间。算法中要取得因子之和,只要在1~m/2之间找到所有整除m的数,将其累加起来即可。如果累加和与m本身相等,则表示m是一个完全数,可以将m 输出。

//  main.cpp
//  dome4
//
//  Created by ExiFeng on 2019/9/26.
//  Copyright © 2019 ExiFeng. All rights reserved.
//

#include <iostream>
#include <cmath>
using namespace std;
方法1
int main()
{
    int i,j,n;
    cout<<"2-1000内的所有完数有:";
    for(i=2; i<=1000; i++)
    {
        n=1;
        for(j=2; j<sqrt(i); j++)
            if(i%j==0)
                n+=(j+i/j);
        if(i==n)
            cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}
//方法2
int main(){
    int i,j,n;
    cout<<"2-1000内的所有完数有:";
    for(i=2; i<=1000; i++)
    {
        n=1;
        for(j=2; j<=i/2; j++)
            if(i%j==0)
                n+=j;
        if(i==n)
            cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

2、问题描述:对于给定的正整数n(n≥1),求1~n构成的集合的所有子集(幂集)。
幂集(Power Set):原集合中所有的子集(包括全集和空集)构成的集族
n为3时,集合为:{1, 2, 3}
所有的子集为:{}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}
总次数=2的n次方

void first(int b[],int n);

int main(){
    int n = 3;
    int a[3] = {1,2,3};
    int b[3] = {0,0,0};
    int i, k;
    int pw = pow(2, n);
    cout << "1—" << n << "的幂集" << endl;
for (i = 0; i < pw; i++) {              
cout << "{";
        for (k = 0; k < n; k++)
            if (b[k])
                cout << a[k];
        cout << "}";
        first(b, n);
    
}
}

void first(int b[],int n){
    for (int i = 0; i < n; i++) {
        if(b[i])
            b[i] = 0;
        else{
            b[i] = 1;
            break;
        }
    }
}

当然,求解幂问题还可以使用回溯法和动态规划法,在这里我仅此列举穷举法,有兴趣的同学们可以自行google。

https://bbs.125.la/forum.php?mod=viewthreadtid=14664204 前天搞到现在,终于搞完了。 设计了一种原理和正则有一点相像的表达式,不是匹配文本,而是穷举生成文本 关键字:`\()<>[]{} 1    aa11    字符 2    aA0    裂变元    a依次裂变a,b,c,...z,0依次裂变0,1,2,...9 3    `01-100`    数值过渡    起始-结束,依次是01,02,03,...100,如果起始小于等于结束,递增过渡,否则递减,可以在较小数值前面补0,指定结果最小长度 4    \PI\    回调cha询    用这个关键词去调用回调函数取结果 0    (aa11)    字符组    括号包含的非关键字识别为字符,整个表达式外层默认识别为一个字符组,即外层出现的非关键字默认识别为字符 0    <aA0>    裂变元组    尖括号包含的非关键字识别为裂变元 5    [123]    可选组    两个结果(选或不选),一个空白,一个123 6    {123(444)}    集合单选组    依次是1,2,3,(444) 四种括号可以任意嵌套,里面的内容含义,取决于由内到外的括号链 同层没有优先级,从右到左进行 //如果设计一个互斥组,可以实现m选n,目前不支持,不偏向这个,也没有更多括号了…… //*3~3 示例: qq<00000>    结果:qq00000,qq00001,qq00002,...qq99999的10w个字符串 id`8-80`    结果:id8,id9,id10,...id80 \time\    结果:16:40,如果指定了回调函数,回调函数cha询time,返回了16:40 {123456789}<0000>    结果:10000-99999 {(123)4}[5]    结果:123,4,1235,45 <0aaa>    结果:1个数字开头,后面3个字母到5个字母的所有组合
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值