蛮力算法
17
main1( ) { int *a,i,j,n; input(n); a=calloc(n+1,sizeof(int)); //申请存储空间 for (i=1; i<=n;i++) a[i]=1; for (i=1; i<=n;i++) for (j=i; j<=n;j=j+i) a[i]=1-a[i]; for (i=1; i<=n;i++) if (a[i]=0) print(i,”is free.”); } 算法分析1:以一次开关锁计算,算法的时间复杂度为 n(1+1/2+1/3+……+1/n)=O(nlogn)。
3
【例3.1】百钱百鸡问题。中国古代数学家张丘建在《算经》 中提出了著名的“百钱百鸡问题”:鸡翁一,值钱五;鸡母一, 值钱三;鸡雏三,值钱一;百钱买百鸡,翁、母、雏各几何? 算法设计1: 通过对问题的理解,可能会想到列出两个三元一次方程, 去解这个不定解方程,就能找出问题的解。这确实是一种办法, 但这里我们要用“懒惰”的枚举策略进行算法设计: 设x,y,z分别为公鸡、母鸡、小鸡的数量。 尝试范围:由题意给定共100钱要买百鸡,若全买公鸡最多 买100/5=20只,显然x的取值范围1~20之间;同理,y的取值范 围在1~33之间,z的取值范围在1~100之间。 约束条件: x+y+z=100 且 5*x+3*y+z/3=100
14
算法如下: main( ) {int i,j,a[100][100],n; input(n); for(i=1;i<=n;i=i+1) for(j=1;j<=n;j=j+1) {if (i=j or i+j=n+1) a [i][j]=0; if (i+j<n+1 and i<j) a [i][j]=1; if (i+j<n+1 and i>j) a [i][j]=2; if (i+j>n+1 and i>j) a [i][j]=3; if (i+j>n+1 and i<j) a [i][j]=4;} for(i=1;i<=n;i=i+1) { print( “换行符”); for( j=1;j<=n;j=j+1) print(a[i][j]); } }
9
算法设计 2 :将算式变形为除法: DDDDDD/A=ABCAB 。 此时只需枚举 A: 3——9 D:1——9,共尝试 7*9=63
次。每次尝试,测试商的万位、十位与除数是否相
同,千位与个位是否相同,都相同时为解。
10
main() {int A,B,C,D,E,F; for(A=3;A<=9;A++) for(D=1;D<=9;D++) { E = D*100000+D*10000+D*1000+D*100+D*10+D; if(E mod A=0) F=E\A; if(F\10000=A and (F mod 100)\10=A) and (F\1000=F mod 10) print( F,”*”,A,”=”,E); } }
print("the chick number is ",z);} } } 算法分析:以上算法只需枚举尝试20*33=660次。实现时约束条 件限定Z能被3整除时,才判断“5*x+3*y+z/3=100”。这样省去 了z不整除3时的算术运算和条件判断,进一步提高了算法效率。
7
【例3.2】解数字迷
A
表3.1
n d(n)
编号与因数个数的关系
11 12 13 14 15 16 „„ 2 6 2 4 4 5 „„
1 2 3 4 5 6 7 8 9 10 1 2 2 3 2 4 2 4 3 4
数学模型2:d(n)有的为奇数,有的为偶数,由于牢房的门开 始是关着的,这样编号为i的牢房,所含1——i之间的不重复 因子个数为奇数时,牢房最后是打开的;反之,牢房最后是 关闭的。
20
算法分析2:
狱吏开关锁的主要操作是a[i]=1- a[i];共执行 n*(1+1/2+1/3+……+1/n)次,时间复杂度近似为O (n logn)。使用了n个空间的一维数组。算法2没 有使用辅助空间,但由于求一个编号的因子个数也 很复杂,其主要操作是判断i mod j是否为0,共执 行了1+2+3+……+n次,时间复杂度为O(n2 /2)。
数学模型3:仔细观察表3.1,发现当且仅当n为完全平方 数时,d(n)为奇数;这是因为n的因子是成对出现的,也即 当n=a*b且a≠b时,必有两个因子a,b; 只有n为完全平方 数,也即当n=a2时,才会出现d(n)为奇数的情形。 算法设计3:只需找出小于n的平方数即可。
蛮力法并不总是因为减少了人脑的思维,就一 定是效率差的算法。对规模不是太大的问题, 蛮力法还是一种比较好的算法策略。
21
表3.1
n d(n) 1 1 2 2 3 2 4 3 5 2 6 4
编号与因数个数的关系
7 2 8 4 9 3 10 4 11 2 12 6 13 2 14 4 15 4 16 „„ 5 „„
2
1 枚举法
枚举法(穷举法)是蛮力策略的一种表现形式,根据问题 中条件将可能情况一一列举出来,逐一尝试从中找出满足 问题条件的解。但有时一一列举出的情况数目很大,则需 要进一步考虑,排除一些明显不合理的情况,尽可能减少 问题可能解的列举数目。 通常从两个方面进行算法设计: 1)找出枚举范围:分析问题所涉及的各种情况。 2)找出约束条件:分析问题的解需要满足的条件,并 用逻辑表达式表示。
11
【例3.3】编程打印有如下规律的n×n方阵。
例如下图:使左对角线和右对角线上的元素为0,它们 上方的元素为1,左方的元素为2,下方元素为3,右方 元素为4,下图是一个符合条件的5阶矩阵。
0 2 2 2 0 1 0 2 0 3 1 1 0 3 3 1 0 4 0 3 0 4 4 4 0
12
构造趣味矩阵:经常用二维数组来解决
8
算法1如下: 算法分析1:该算法 main( ) 的尝试范围是A: { int A,B,C,D,E,E1,F,G1,G2,i; 3—9,B:0—9, C:0—9 。共尝试 for(A=3; A<=9; A++) 700次,不是一个 for(B=0; B<=9; B++) 好的算法。 for(C=0; C<=9; C++) { F=A*10000+B*1000+C*100+A*10+B; E=F*A; E1=E; G1=E1 mod 10; for(i=1; i<=5; i++) { G2=G1; E1=E1/10; G1= E1 mod 10; if(G1<>G2 ) break; } if(i=6) print( F,”*”,A,”=”,E); } }
15
【例3.5】狱吏问题 某国王对囚犯进行大赦,让一狱吏n次通过一排锁着 的n间牢房,每通过一次,按所定规则转动n间牢房中的某 些门锁, 每转动一次, 原来锁着的被打开, 原来打开的被 锁上;通过n次后,门锁开着的,牢房中的犯人放出,否则 犯人不得获释。 转动门锁的规则是这样的,第一次通过牢房,要转动 每一把门锁,即把全部锁打开;第二次通过牢房时,从第 二间开始转动,每隔一间转动一次;第k次通过牢房,从第 k间开始转动,每隔k-1 间转动一次;问通过n次后,哪些 牢房的锁仍然是打开的?
18
问题分析2:转动门锁的规则可以有另一种理解,第一次转动 的是编号为1的倍数的牢房;第二次转动的是编号为2的倍数 的牢房;第三次转动的是编号为3的倍数的牢房;„„则狱吏 问题是一个关于因子个数的问题。 令d(n)为自然数n的因子个数,这里不计重复的因子,如4 的因子为1,2,4共三个因子,而非1,2,2,4。则d(n)或为 奇数,或为偶数,见下表:
4
算法1如下: 算法分析:此算 法需要枚举尝试 main( ) 20*34*100=68000 { int x,y,z; 次。算法的效率 for(x=1;x<=20;x=x+1) 显然太低。 for(y=1;y<=34;y=y+1) for(z=1;z<=100;z=z+1) if(100=x+y+z and 100=5*x+3*y+z/3) {print("the cock number is",x); print("the hen number is", y); print("the chick number is ",z); } }
19
算法设计2: 1)算法是求出每个牢房编号的不重复的因子个数,当它为 奇数时,这里边的囚犯得到大赦。 2)一个数的因子是没有规律的,只能从1——n枚举尝试。 main2( ) { int s,i,j,n; input(n); for (i=1; i<=n;i++) 为什么从2开始? { s=1; for (j=2; j<=i;j=j++) if (i mod j=0) s=s+1; if (s mod 2 =1) print(i,”is free.”); } }
第3章 蛮力法
计 算
i 1 ji 1
i 1
i 1
机 学
(n 1) (n 2) (n 3) 3 2 1
院
黄
襄 念
结论
n(n 1) (n2 ) 2
1. 选择排序算法效率属于 (n2 ) 型
2. 元素交换次数 (n 1) (n),该特性使选择排序算法效率超过了
学 增长函数:
数
n1 ni
n1
n1
学 与
T(n) 1 [(n i 1) 1] [n i]
计 算
i 1 j1
i 1
i 1
机 学 院
n(n 1) (n2 ) 2
黄 结果讨论:
襄 念
1. 冒泡排序算法效率属于(n2 ) 类型 —— 与选择排序相同
描述:在一个包含 n 个点的点集中,找到距离最近的两个点
西 简化:二维平面上两点 Pi (xi , yi) 和 Pj (xj , yj) 的欧氏距离
华
大 学
d(Pi , Pj ) ( xi x j )2 ( yi y j )2
数 学
蛮力法:穷举计算 每一对点 的距离,然后找出距离最小的那对点。
大
学 顺序查找的蛮力法
数 学
查找键与表中元素从头至尾逐个比较。结果:找到 或 失败
与 计
限位器:把查找键添加到列表末尾—— 一定成功,避免每次循环时
算
对检查是否越界(边界检查)
机
学 院
SequentialSearch( A[0...n], K ) {
最佳效率:Tbest (n) = 1 最差效率:Tworst(n) = n + 1
算法设计与分析-第3章-蛮力法
哨兵
0123456789 k 10 15 24 6 12 35 40 98 55
查找方向
i
清华大学出版社
算法设计与分析
算法3.2——改进的顺序查找
int SeqSearch2(int r[ ], int n, int k) //数组r[1] ~ r[n]存放查找集合 { r[0]=k; i=n; while (r[i]!=k)
清华大学出版社
算法设计与分析
第3章 蛮力法
3.1 蛮力法的设计思想 3.2 查找问题中的蛮力法 3.3 排序问题中的蛮力法 3.4 组合问题中的蛮力法 3.5 图问题中的蛮力法 3.6 几何问题中的蛮力法 3.7 实验项目——串匹配问题
清华大学出版社
算法设计与分析
3.1 蛮力法的设计思想
蛮力法的设计思想:直接基于问题的描述。 例:计算an
52 37 65 不可行 不可行 不可行 不可行 不可行
清华大学出版社
算法设计与分析
对于一个具有n个元素的集合,其子集 数量是2n,所以,不论生成子集的算法 效率有多高,蛮力法都会导致一个Ω(2n) 的算法。
清华大学出版社
算法设计与分析
3.4.4 任务分配问题
假设有n个任务需要分配给n个人执行, 每个任务只分配给一个人,每个人只分配一 个任务,且第j个任务分配给第i个人的成本 是C[i, j](1≤i , j≤n),任务分配问题要求 找出总成本最小的分配方案。
用蛮力法解决0/1背包问题,需要考虑给定n个 物品集合的所有子集,找出所有可能的子集(总重 量不超过背包容量的子集),计算每个子集的总价 值,然后在他们中找到价值最大的子集。
清华大学出版社
算法设计与分析
10
蛮力法
i 0 nm
1 [(m 1) 1] (n m 1)m
j 0 i 0
m 1
nm
第三章 蛮力法
3.2 最近对问题 算法:BruteForceClosetPoints(P)
//该算法实现了蛮力法球平面中距离最近的两个点 //输入:一个n个(n>1)个点的列表,P1=(X1,Y1)…… ,Pn=(Xn,Yn) //输出:最近的两个点得下标,index1和index2
C( n )
n 1 i 1
1
i 1 j i 1k 1 n n) n( n i )
j i 1
n[(n 1)(n 2) 1] n 2 ( n 1) / 2
第三章 蛮力法
3.4 旅行商问题 算法:TSP(P[1..n],V[1..n][1..n])
C( n )
i 1 n 1
j i 1
2 [2(n i)] 2[(n 1 1)(n 1)] / 2 n(n 1)
i 1
n
n 1
第三章 蛮力法
3.3 凸包问题 算法:BruteForceConvexHull(P)
//该算法实现了蛮力法求平面中距离最近的两个点 //输入:一个n个(n>1)个点的列表,P1=(X1,Y1)…… ,Pn=(Xn,Yn) //输出:最小凸集合集合S
2 3 n C( n) c11 cn cn cn 2n 1 n
第三章 蛮力法
3.4 旅行商问题 效率分析: TSP(P[1..n],V[1..n][1..n]) //对于具有n个节点的哈密顿回路而言,必须生成一个由n+1 个节点构成的序列,其入口和出口假设为节点1,那么蛮 力法必须生成所有其他的n-1个节点构成一条完整的路径 //显然,对于这样一个算法而言,蛮力法求旅行商问题总是 一个效率为θ((n-1)!)的算法
蛮力算法的特点范文
蛮力算法的特点范文蛮力算法(Brute-Force Algorithm)是一种简单直接、不依赖与特定问题领域知识的解决问题的方法。
它通过尝试所有可能的解,然后比较它们的结果来达到问题求解的目标。
蛮力算法的主要特点如下:1.直接暴力:蛮力算法不依赖于任何问题的特定知识,它直接从问题的定义出发,尝试所有可能的解,找到最优解。
这种直接暴力的方法保证了算法的通用性和适用性,适用于各种类型的问题。
2.简单易懂:蛮力算法的实现通常很简单直观,思路清晰。
它不需要过多的问题分析和优化技巧,避免了复杂的数学推导和算法设计。
相对于其他高级算法,蛮力算法容易理解和实现。
3.穷尽所有可能性:蛮力算法通过列举所有可能的解来寻找最优解。
它不会漏掉任何可能的解,同时也不会因为其中一种假设或剪枝操作而丢失最优解。
蛮力算法的穷举特性保证了结果的准确性。
4.时间复杂度高:蛮力算法的主要缺点是其时间复杂度通常较高。
由于蛮力算法需要遍历所有可能的解,所以算法的时间复杂度很容易达到指数级别。
这意味着对于大规模问题,蛮力算法的执行时间可能会非常长。
5.可以用于验证其他算法:蛮力算法具有确定性和可靠性的特点。
因此,它常常被用于验证其他算法的正确性。
通过比较其他算法的结果和蛮力算法的结果,可以判断其他算法的准确性和可行性。
6.常用于小规模问题:尽管蛮力算法的时间复杂度较高,但对于小规模问题,蛮力算法仍然是一个可行的求解方法。
在问题规模较小的情况下,蛮力算法通常能够在较短的时间内给出结果。
7.可用于优化问题:蛮力算法也可以用于优化问题。
通过遍历所有可能的解,可以找到问题的最优解或近似最优解。
虽然时间复杂度较高,但对于一些优化问题,蛮力算法依然是一种可行的求解方法。
8.需要合理的问题建模:蛮力算法的有效性和效率很大程度上依赖于问题的建模。
将问题正确地建模为待求解的空间,是保证蛮力算法正确性的前提。
合理的问题建模可以减少问题空间的范围,从而提高蛮力算法的效率。
ACM蛮力(穷举)PPT课件
chicken=%-2d\n", j, x, y, z); j++;} } }
.
10
运行结果: Possible solutions to buy 100 fowls whith 100 wen:
1: cock=0 hen=25 chicken=75 2: cock=4 hen=18 chicken=78 3: cock=8 hen=11 chicken=81 4: cock=12 hen=4 chicken=84
.
14
#include "stdio.h" main() { int m, count=0;
运行结果: 52 157 262 367 472 577 682 787 892 997
for ( m=1; m<=1000; m++ )
if ( m%3==1&&m%5==2&&m%7==3)
{ printf("%5d",m);
count++;
if(count%5==0) printf("\n");
}
}
.
15
常用的蛮力法
1.搜索所有的解空间。 2.搜索所有的路径。 3.直接进行计算。
.
16
搜索所有的解空间
案例1:假金币 案例2:现在的时间是多少?
.
17
案例1:假金币
False coin
Time Limit:3000MS Memory Limit:10000K
蛮力法是一种直接解决问题的方法,常常 直接基于问题的描述和所涉及的概念定义。
蛮力算法的基本条件
蛮力算法的基本条件
我觉得这蛮力算法啊,它得有几个基本条件。
首先呢,得是直来直去的那种思维,就像我老家村里头的二柱子,那家伙,脑子一根筋。
看他那模样,脸黑黝黝的,眼睛瞪起来像铜铃,头发乱得跟鸡窝似的,每次决定做啥事儿,就直接冲着目标去,啥弯儿都不拐,这就有点蛮力算法那味儿。
这算法得有个明确的目标,就好比我去集上找老王头买他那只芦花鸡。
我心里就想着那只芦花鸡,其他鸡啊鸭啊的,我看都不看。
我到了集上,人挤人,那气味儿啊,混杂着鸡屎味、汗臭味,还有各种小吃的香味儿。
可我不管这些,我就一门心思找老王头和他的芦花鸡。
这目标明确了,才好施展这蛮力算法。
还有啊,这算法不能怕麻烦。
我记得有次我想找个旧书,那书可稀罕了,在一堆旧书堆里找。
那些书啊,堆得像小山似的,灰扑扑的,有的还破破烂烂。
我就一本一本地翻,旁边有人就笑我,说我傻,这么多书咋找得到。
我就跟他说,“你懂啥,我这就是要找,哪怕把这堆书全翻遍喽。
”这就像蛮力算法,不管多麻烦,就是一个劲儿地干。
再有呢,这蛮力算法在做的时候,还不能想太多旁的东西。
我有一回跟人打赌,看谁先把一块地的杂草拔完。
我就蹲下来,开始拔草。
旁边那人呢,一会儿看看天,一会儿看看地,还跟路过的人聊天。
我就不管,我就看着我眼前的草,一根一根地拔。
那草的叶子刺得我手痒痒的,我也不管,就这么干。
这就像蛮力算法,专注于自己要做的事儿,其他的都先放一边。
这蛮力算法啊,说起来简单,但真要做起来,也得有点像我这样的憨劲儿才行。
蛮力法
2 查找问题中的蛮力法—串的匹配
BF算法
KMP算法
下一次开始位置 下一次开始位置
本趟开始位置
i 回溯
ii
S 模式T
si
…
tj
回溯
j
j
回溯next[j]
……
3 排序问题中的蛮力法—选择排序
选择排序开始的时候,扫描整个序列,找到整个序列的最小记
录和序列中的第一个记录交换,从而将最小记录放到它在有序
区的最终位置上,然后再从第二个记录开始扫描序列,找到n-1
个序列中的最小记录,再和第二个记录交换位置。一般地,第i
趟排序从第i个记录开始扫描序列,在n-i+1(1≤i≤n-1)个记录中
找到关键码最小的记录,并和第i个记录交换作为有序序列的第i
个记录。
4 组合问题中的蛮力法—任务分配问题
可以用一个n元组(j1, j2, …, jn)来描述任务分配问题的一个可能 解,其中第i个分量ji(1≤i≤n)表示在第i行中选择的列号,因此 用蛮力法解决任务分配问题要求生成整数1~n的全排列,然后把 成本矩阵中的相应元素相加来求得每种分配方案的总成本,最 后选出具有最小和 18
是否最短
否 是 否 是 否 否
蛮力法求解TSP问题存在的问题
注意到图中有3对不同的路径,对每对路径来说,不同 的只是路径的方向,因此,可以将这个数量减半,则 可能的解有(n-1)!/2个。随着n的增长,TSP问题的可 能解也在迅速地增长。
一个10城市的TSP问题有大约180,000个可能解。 一个20城市的TSP问题有大约
依次处理所有元素是蛮力法的关键,为 了避免陷入重复试探,应保证处理过的 元素不再被处理。
第4章 蛮力法
for (i=0;i<n;i++)
//两重循环穷举所有的连续子序列
{ for (j=i;j<n;j++) { thisSum=0; for (k=i;k<=j;k++) thisSum+=a[k]; if (thisSum>maxSum) //通过比较求最大连续子序列之和 maxSum=thisSum; }
第4章 蛮力法
4.1 蛮力法概述 4.2 蛮力法的基本应用 4.3 递归在蛮力法中的应用
4.1 蛮力法概述
• 蛮力法也称穷举法,枚举法,暴力法,是一种简单直接地 解决问题的方法,是算法中最常用的方法之一
• 通常直接基于问题的描述和所涉及的概念定义,找出所有 可能的解。然后选择其中的一种或多种解,若该解不可行 则试探下一种可能的解。
//进行n-1趟排序
{
} }
exchange=false;
//本趟排序前置exchange为false
for (j=n-1;j>i;j--)
//无序区元素比较,找出最小元素
if (a[j]<a[j-1])
//当相邻元素反序时
{ swap(a[j],a[j-1]); //a[j]与a[j-1]进行交换
for (m=2;m<=1000;m++) { 求出m的所有因子之和s;
if (m==s) 输出s; }
对应的程序如下:
void main() { int m,i,s;
for (m=2;m<=1000;m++) { s=0;
for (i=1;i<=m/2;i++) if (m%i==0) s+=i; //i是m的一个因子
算法设计(第3章蛮力法)
d = dx*dx + dy*dy;
if (d<d_best) then
d_best d;
(a,b) (i,j);
return (a,b);
时间复杂度O(n2):存在改进可能?
end
3.5.2 (0-1)背包问题
输入:n件物品的集合S (其中第i件物品的重量 和价值分别为S[i].w和S[i].v),以及背包的最大 承重量W
[最小顶点覆盖问题的蛮力算法]
Algorithm Brute_VertexCover(V: set<int>; E: set<intint>)
begin
let C = V;
foreach V’ Powerset(V) do
let cover = true;
foreach ((u,v) E) do
3.1 字符串匹配
蛮力法:从左到右扫描T,检查T中是否含有子串P
m i c r o s o f t wi n dows sof t
匹配成功,返回位置索引5
3.1 字符串匹配
[字符串匹配算法] Algorithm Brute_Match(T, P: string) begin let i = 0, n = |T|, m = |P|; while (i ≤ n−m) do
时间复杂度O(n2)
3.5 若干最优化问题最优化问 Nhomakorabea:在问题的可行域F中找到一个解x, 使得某目标函数值f(x)最小或最大。
约束条件:解x应满足某项约束c(x)=true 连续优化问题:解的数量可能有无穷多 组合优化问题:解的数量有限时,总是可以用
蛮力法求解,但算法效率可能很低。
3.5 若干最优化问题
蛮力法 (2)
11
【例】贴纸问题 有A、B、C、D、E五人,每人额头上都帖了一张黑或白的纸。五人对 坐,每人都可以看到其他人额头上的纸的颜色。五人相互观察后, A说:“我看见有三人额头上帖的是白纸,一人额头上帖的是黑纸” B说:“我看见其他四人额头上帖的都是黑纸” C说:“我看见有一人额头上帖的是白纸,其他三人额头上帖的是黑纸” D说:“我看见其他四人额头上帖的都是白纸” E说:什么也没有说 现在已知额头上帖黑纸的人说的都是谎话,额头上贴白纸的人说的都 是实话,请你编写程序,求出这五个人谁的额头上帖的白纸,谁的额 头上帖的黑纸。
蛮力算法的优缺点:
(1)可以用来解决广阔领域的问题; (2)算法设计思想简单明了; (3)可以解决一些小规模的问题; (4)算法的效率不高,随着问题规模的增大,算法效率急剧下降; (5)问题规模过大时,在时间上,有些蛮力算法不可行。
15
作业1:用蛮力算法求解古堡问题
福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式: ABCDE * ? = EDCBA 他对华生说:“ABCDE应该代表不同的数字,问号也代表某个数字!” 华生:“我猜也是!” 于是,两人沉默了好久,还是没有算出合适的结果来。 请你利用计算机的优势,找到破解的答案。 把 ABCDE 所代表的数字写出来。
蛮力法
1
蛮力法
蛮力法是基于计算机运算速度快这一特性,在解决问题 时采取的一种“懒惰” 策略。这种策略不经过(或者说经过 很少)思考,把问题所有情况或所有过程交给计算机去一 一尝试,从中找出问题的解。 蛮力策略应用:选择排序、冒泡排序、插入排序、顺序 查找、朴素的字符串匹配等。比较常用还有枚举法、盲目
搜索算法等。
2
1 枚举法
枚举法(穷举法)是蛮力策略的一种表现形式,根据问题 中条件将可能情况一一列举出来,逐一尝试从中找出满足 问题条件的解。但有时一一列举出的情况数目很大,则需 要进一步考虑,排除一些明显不合理的情况,尽可能减少 问题可能解的列举数目。 通常从两个方面进行算法设计: 1)找出枚举范围:分析问题所涉及的各种情况。 2)找出约束条件:分析问题的解需要满足的条件,并 用逻辑表达式表示。
