写在前面,关于穷举法的定义自行去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
#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。