枚举算法(百钱百鸡问题 C语言)

枚举

首先,最为简单的思想,枚举算法。枚举也叫穷举,顾名思义,就是穷尽列举。枚举思想的应用场景十分广泛,也非常容易理解。简单来说,枚举就是将问题的可能解依次列举出来,然后一一带入问题检验,从而从一系列可能解中获得能够解决问题的精确解。

枚举虽然看起来简单,但是其实还是有一些容易被人忽视的考虑点。比方说待解决问题的「可能解/候选解」的筛选条件,「可能解」之间相互的影响,穷举「可能解」的代价,「可能解」的穷举方式等等。

很多时候实际上不必去追求高大上的复杂算法结构,反而大道至简,采用枚举法就能够很好的规避系统复杂性带来的冗余,同时或许在一定程度上还能够对空间进行缩减。
枚举思想的流程可以用下图来表示。通过实现事先确定好「可能解」,然后逐一在系统中进行验证,根据验证结果来对「可能解」进行分析和论证。这是一种很明显的结果导向型的思想,简单粗暴地试图从最终结果反向分析「可能解」的可行性。

在这里插入图片描述
不过,枚举思想的劣势当然也很明显。在实际的运行程序中,能够直接通过枚举方法进行求解的问题少之又少。而当「可能解」的筛选条件不清晰,导致「可能解」的数量和范围无法准确判断时,枚举就失去了意义。

然而当「可能解」的规模比较小,同时依次验证的过程容易实施时,枚举思想不失为一种方便快捷的方式。只不过在具体使用时,还可以针对应用场景对「可能解」的验证进行优化。

这种优化可以从两个方向入手,一是问题的简化,尽可能对需要处理的问题进行模型结构上的精简。这种精简具体可体现在问题中的变量数目,减少变量的数据,从而能够从根本上降低「可能解」的组合。

二是对筛选「可能解」的范围和条件进行严格判断,尽可能的剔除大部分无效的「可能解」。

虽说如此,但是一般而言大部分枚举不可用的场景都是由于「可能解」的数量过多,无法在有限空间或有限时间内完成所有可能性的验证。不过实际上枚举思想是最接近人的思维方式,在更多的时候是用来帮助我们去「理解问题」,而不是「解决问题」。

应用

百钱买百鸡问题。 该问题叙述如下:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,则翁、母、雏各几何?

翻译过来,意思是公鸡一个五块钱,母鸡一个三块钱,小鸡三个一块钱,现在要用一百块钱买一百只鸡,问公鸡、母鸡、小鸡各多少只?

:假设公鸡有x只,母鸡有y只,则小鸡有100-x-y只。可以推出一个等式:5x + 3y + (100-x-y)*1/3 = 100。由于鸡的数量肯定不能为小数,所以我们在等式两边同乘3,变为 15x + 9y + 100-x-y = 300。再化简:14x + 8y = 200;有了该等式,我们的代码就显得很简单了。

//公鸡一个五块钱,母鸡一个三块钱,小鸡三个一块钱,
//现在要用一百块钱买一百只鸡,问公鸡、母鸡、小鸡各多少只?
int BuyChicken(int price, int num)// 钱, 只
{
    int total = 0;
    for (int x = 0; x < num / 5; ++x)
    {
        for (int y = 0; y < num / 3; ++y)
        {
            int z = num - x - y;
            //15*x + 9*y + z = 3*price
            if (14 * x + 8 * y == 2 * price)
            {
                ++total;
                printf("公鸡:%d, 母鸡:%d, 小鸡:%d, \n", x, y, z);
            }
        }
    }
    return total;
}

int main()
{
    int price = 100;
    int num = 100;
    int res = BuyChicken(price, num);
    printf("花%d块钱买%d只鸡共有%d中方案\n", price, num, res);
    return 0;
}

运行结果:
在这里插入图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WhiteShirtI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值