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

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

一、使用技术

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

二、适用范围

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

三、求解过程

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

四、基本格式

入门算法-穷举法(计算完全数和求解幂集问题)_第1张图片

五、例题

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 
#include 
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。

你可能感兴趣的:(算法)