1-5、算法设计常用思想之穷举法

穷举法又称穷举搜索法,是一种在问题域的解空间中对所有可能的解穷举搜索,并根据条件选择最优解的方法的总称。数学上也把穷举法称为枚举法,就是在一个由有限个元素构成的集合中,把所有元素一一枚举研究的方法。

使用穷举法解决问题,基本上就是以下两个步骤:
  • 确定问题的解(或状态)的定义、解空间的范围以及正确解的判定条件;
  • 根据解空间的特点来选择搜索策略,逐个检验解空间中的候选解是否正确;

解空间的定义
解空间就是全部可能的候选解的一个约束范围,确定问题的解就在这个约束范围内,将搜索策略应用到这个约束范围就可以找到问题的解。要确定解空间,首先要定义问题的解并建立解的数据模型。如果解的数据模型选择错误或不合适,则会导致解空间结构繁杂、范围难以界定,甚至无法设计穷举算法。
穷举解空间的策略
穷举解空间的策略就是搜索算法的设计策略,根据问题的类型,解空间的结构可能是线性表、集合、树或者图,对于不同类型的解空间,需要设计与之相适应的穷举搜索算法。简单的问题可以用通用的搜索算法,比如线性搜索算法用于对线性解空间的搜索,广度优先和深度优先的递归搜索算法适用于树型解空间或更复杂的图型解空间。

盲目搜索和启发式搜索
对于线性问题的盲目搜索,就是把线性表中的所有算法按照一定的顺序遍历一遍,对于复杂问题的盲目搜索,常用广度优先搜索和深度优先搜索这两种盲目搜索算法。
如果搜索能够智能化一点,利用搜索过程中出现的额外信息直接跳过一些状态,避免盲目的、机械式的搜索,就可以加快搜索算法的收敛,这就是启发性搜索。启发性搜索需要一些额外信息和操作来“启发”搜索算法,根据这些信息的不同,启发的方式也不同。

剪枝策略
对解空间穷举搜索时,如果有一些状态节点可以根据问题提供的信息明确地被判定为不可能演化出最优解,也就是说,从此节点开始遍历得到的子树,可能存在正确的解,但是肯定不是最优解,就可以跳过此状态节点的遍历,这将极大地提高算法的执行效率,这就是剪枝策略,应用剪枝策略的难点在于如何找到一个评价方法(估值函数)对状态节点进行评估。特定的评价方法都附着在特定的搜索算法中,比如博弈树算法中常用的极大极小值算法和“α-β”算法,都伴随着相应的剪枝算法。

剪枝和启发
剪枝不是启发性搜索。剪枝的原理是在结果已经搜索出来或部分搜索出来(比如树的根节点已经搜索出来了,但是叶子节点还没有搜索出来)的情况下,根据最优解的判断条件,确定这个方向上不可能存在最优解,从而放弃对这个方向的继续搜索。而启发性搜索通常是根据启发函数给出的评估值,在结果出来之前就朝着最可能出现最优解的方向搜索。它们的差异点在于是根据结果进行判断还是根据启发函数的评估值进行判断。

搜索算法的评估和收敛
收敛原则是只要能找到一个比较好的解就返回(不求最好),根据解的评估判断是否需要继续下一次搜索。大型棋类游戏通常面临这种问题,比如国际象棋和围棋的求解算法,想要搜索整个解空间得到最优解目前是不可能的,所以此类搜索算法通常都通过一个搜索深度参数来控制搜索算法的收敛,当搜索到指定的深度时(相当于走了若干步棋)就返回当前已经找到的最好的结果,这种退而求其次的策略也是不得已而为之

百钱买鸡问题
一百个钱买一百只鸡,是个典型的穷举法应用。问题描述:每只大公鸡值 5 个钱,每只母鸡值 3 个钱,每 3 只小鸡值 1 个钱,现在有 100 个钱,想买 100 只鸡,问如何买?有多少种方法?

void Buy()
{
    int count = 0;

    for (int roosters = 0; roosters <= 20; roosters++)   //枚举大公鸡数量
    {
        for (int hens = 0; hens <= 33; hens++) //枚举母鸡数量
        {
            int chicks = 100 - roosters - hens;  //剩下的就是小鸡数量
            if (((chicks % 3) == 0) //小鸡个数应该是 3 的整数倍,算是个小小的剪枝
                && ((5 * roosters + 3 * hens + chicks / 3) == 100)) //是否凑够 100 钱
            {
                count++;
                std::cout << "买法 " << count << ":公鸡 " << roosters
                                              << ", 母鸡 " << hens
                                              << ", 小鸡 " << chicks << std::endl;
            }
        }
    }

    std::cout << "共有 " << count << " 种买法" << std::endl;
}
-- lua实现
function bug()
    local count = 0
    for roosters = 0, 20 do
        for hens = 0, 33 do
            local chicks = 100 - roosters - hens
             if (((chicks % 3) == 0) and ((5 * roosters + 3 * hens + chicks / 3) == 100)) then
                 count = count + 1
                 print("====买法", count, roosters, hens, chicks)
             end
        end
    end
    print("====共有买法", count)
end

鸡兔同笼问题

有鸡和兔在一个笼子中,数头共 50 个头,数脚共 120 只脚,问:鸡和兔分别有多少只?

for ji = 1, 50 do
    local tu = 50 - ji
    if (tu * 4 + ji * 2) == 120 then
        print("===========鸡 兔各", ji, tu)
        break
    end
end

原文地址:https://www.cnblogs.com/orxx/p/10947129.html

时间: 2025-01-04 22:52:47

1-5、算法设计常用思想之穷举法的相关文章

1-6、算法设计常用思想之迭代法

人们提出了很多迭代法来近似求解这类问题,比较常见的有梯度法.最小二乘法和牛顿迭代法,只要问题的解是可收敛的(或者是局部可收敛的),都可以使用迭代法求解. 数学意义上的迭代法是一种不断用变量的旧值递推新值的过程,其对应的迭代算法也是用计算机解决问题的一种基本方法. 迭代法和递推法的关系迭代法作为很多数学问题的求解算法,是解决数学问题的一种常用的算法模式,可以独立构成解决问题的算法.递推法作为一种设计算法的常用思想,没有固定的算法实现模式,通常是与其他算法模式配合形成算法实现.比如线性动态规划问题,

算法问题------爬梯子问题 穷举法 递归法 动态规划 简单循环

http://home.juedui100.com/user/24086697.htmlhttp://home.juedui100.com/user/24081650.htmlhttp://home.juedui100.com/user/24050915.htmlhttp://home.juedui100.com/user/24083352.htmlhttp://home.juedui100.com/user/24061195.htmlhttp://home.juedui100.com/user

《算法问题实战策略》-chaper7-穷举法

关于这一章节<算法实战策略>有一段概述问题,我认为对于编程人员来说非常有价值,故在这里进行如下的摘抄: 构想算法是很艰难的工作.相比大家都经历过,面对复杂的要求只是傻乎乎地盯着显示器,或者不经过深思熟虑就开始打键盘,结果还要辛辛苦苦修改变得一塌糊涂的代码.经过这些磨难,各位就能切身体会到设计算法的重要性. 与通常所想不同,支配设计算法的并不是一时的灵感,而是许多策略性的选择.构想算法不仅需要理解问题的特性,还要理解执行时间和占用内存空间之间的对立关系,而且要会选择适当的数据结构. 算法设计范式

算法基础一 穷举法

/*穷举法*/ /*鸡兔同笼35头,94足,鸡兔各几只?*/ #include<stdio.h> const int Num = 35; const int Foots = 94; int main() { int cN;//鸡 int rN;//兔 for (cN = 0; cN <= 35; cN++) { rN = Num - cN; if (Foots == cN * 2 + rN * 4 ) { printf("鸡:%d,兔:%d\n",cN,rN); }

什么叫穷举法?

穷举法的基本思想是根据题目的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到全部情况验证完毕.若某个情况验证符合题目的全部条件,则为本问题的一个解:若全部情况验证后都不符合题目的全部条件,则本题无解.穷举法也称为枚举法. 用穷举法解题时,就是按照某种方式列举问题答案的过程.针对问题的数据类型而言,常用的列举方法一有如下三种: (1)顺序列举 是指答案范围内的各种情况很容易与自然数对应甚至就是自然数,可以按自然数的变化顺序去列举. (2)排列列举 有时答案的数据形式是一组数的

C#跳转语句 迭代法 穷举法

一.跳转语句 break & continue break:跳出循环,终止此循环,不管下面还有多少次,全部跳过. string a=" ", for (int i=1;i<=10;I++) { if(i==5) { break; } a += i +",": } Console.WriteLine(a); 输出结果为 1,2,3,4,5 continue:终止此次循环,直接开始下次循环. string a=" ", for (int

003-算法-穷举法

一.概念: 基本思想是根据题目的部分条件确定答案的大致范围,并在方位内对所有可能的情况注意验证.穷举法也称为枚举法. 用穷举发解题时,就是按照某种方式列举问题答案的过程.针对问题的数据类型而言,常用的列举方法有如下三种: 1)顺序列举 2)排列列举 3)组合列举 穷举法 ,比较好理解 .不做demo代码示例 003-算法-穷举法

XTU OJ 1175 Hurry Up(三分法&amp;&amp;穷举法)

 Hurry Up Accepted : 88   Submit : 345 Time Limit : 1000 MS   Memory Limit : 65536 KB Problem Description GG is some what afraid of his MM. Once his MM asks, he will always try his best to rush to their home. Obvious, he can run home in straight li

穷举法解决旅行商问题

一.问题描述 如图所示,一个旅行商从A点出发,需要不重复地走遍5个城市ABCDE,最后回到A.每个城市之间的花费(即权值)如图所示,现在要求找出一条总花费最小的路径,即权值和为最小的路径. 二.     算法说明 1.    算法一: 登山法(贪心法) 即在每一个城市出发前比较接下来所能走的城市花费(权值),找出权值最小的走. 优缺点:由于只是在每个城市局部地考虑权值最小,但当走完所用城市后,所得到权值和不一定为最小,所以采用此算法得不到精确解,但此算法复杂度较低. 2.  算法二:穷举法(本程