枚举算法实例应用(一)

简介: 枚举算法实例应用,包括完美立方式判定、生理高峰问题、Counterfeit Dollar(POJ)问题。

枚举算法实例应用

第一题:Counterfeit Dollar

Description

Sally Jones has a dozen Voyageur silver dollars. However, only eleven of the coins are true silver dollars; one coin is counterfeit even though its color and size make it indistinguishable from the real silver dollars. The counterfeit coin has a different weight from the other coins but Sally does not know if it is heavier or lighter than the real coins.
Happily, Sally has a friend who loans her a very accurate balance scale. The friend will permit Sally three weighings to find the counterfeit coin. For instance, if Sally weighs two coins against each other and the scales balance then she knows these two coins are true. Now if Sally weighs
one of the true coins against a third coin and the scales do not balance then Sally knows the third coin is counterfeit and she can tell whether it is light or heavy depending on whether the balance on which it is placed goes up or down, respectively.
By choosing her weighings carefully, Sally is able to ensure that she will find the counterfeit coin with exactly three weighings.

Input

The first line of input is an integer n (n > 0) specifying the number of cases to follow. Each case consists of three lines of input, one for each weighing. Sally has identified each of the coins with the letters A--L. Information on a weighing will be given by two strings of letters and then one of the words ''up'', ''down'', or ''even''. The first string of letters will represent the coins on the left balance; the second string, the coins on the right balance. (Sally will always place the same number of coins on the right balance as on the left balance.) The word in the third position will tell whether the right side of the balance goes up, down, or remains even.

Output

For each case, the output will identify the counterfeit coin by its letter and tell whether it is heavy or light. The solution will always be uniquely determined.

Sample Input

1 
ABCD EFGH even 
ABCI EFJK up 
ABIJ EFGH even 

Sample Output

K is the counterfeit coin and it is light. 
简言之:有12枚硬币,其中有11枚真币和1枚假币。假币、真币重量不同,但不知假币比真币轻还是重。现用天平称了三次(两边币数相同),已知称重三次的结果,求出假币并确定假币比真币轻还是重 (数据保证一定能找出来)。

首先,大体思路为:

利用反证法

  1. 先假设A是假币,并且A是轻的,把A是轻的带入天平的三次比对中,判断是否与结论矛盾,若有一个或多个矛盾,则条件不成立,即A不是轻的假币;若均成立,则证明题设成立,即A为轻的假币。
  2. 若1条件不成立,则假设A是重的假币,再将该条件带入天平的三次比对中,判断是否与结论矛盾,若有一个或多个矛盾时,则条件不成立,即A不是重的假币;若均成立,则证明题设成立,即A为轻的假币。
  3. 若1、2条件同时不成立,则A为真币。再返回步骤1继续判断‘A’++,即下一个字符‘B’。直到最后一个字符‘L’。

  • 可以采用三个数组来存储天平的左边、右边、和平衡结果。
//12个硬币最多 一边6个,故列选为6
char Left[3][6] = {"ABCD", "ABCI", "ABIJ"};    //天平左边的硬币
char Right[3][6] = {"EFGH", "EFJK", "EFGH"};   //天平右边的硬币
char Result[3][4] = {"even", "up", "even"};    //结果数组

通过CounterfeitDollar函数实现步骤1~3。

void CounterfeitDollar() {
    for (char c = 'A'; c <= 'L'; c++) {//十一个硬币即A~K
        if (IsFake(c, true)) {//假设c为假币,且是轻的,判断是否满足为假的条件
            printf("%c is the counterfeit coin and it is light.\n", c);
            break;
        } else if (IsFake(c, false)) {//若不满足,则假设c是重的假币,判断是否满足c为假的条件
            printf("%c is the counterfeit coin and it is heavy.\n", c);
            break;
        }
    }
}

其中IsFake(char c,bool light)为假设与三次输入的天平结果比较的结果。只要与其中任何一个结果不匹配则表示假设不成立,均匹配时则表示假设成立,即得出对应解。

其中,为了保证假币无论是轻还是重,都能使三次天平结果的判断代码统一,在3~10行中,通过指针及轻重情况指针指示的对调实现代码统一。

代码详细解释见代码段中注释。

bool IsFake(char c, bool light) {   //light=TRUE表示假币为轻,否则表示为重。
    for (int i = 0; i < 3; ++i) {
        char *pLeft, *pRight;       //天平两边字符串的指针。
        if (light) {                //若硬币为轻的假币。
            pLeft = Left[i];        //第i次称量时,天平左边的字符串。
            pRight = Right[i];      //第i次称量时,天平右边的字符串。
        } else {                    //若硬币为重的假币
            pLeft = Right[i];       //对调左右称量结果
            pRight = Left[i];       //使得Switch中算法恒成立
        }
        //在Switch中我们假设c是轻的假币,因为上述的结果对调使得在Switch中算法不受轻重影响,恒成立。
        switch (Result[i][0]) {     //天平右边三种情况的分支,
            case 'u':               //即up,若右边上升,即表示右边轻,那么假币c一定出现在天平的右边
                if (strchr(pRight, c) == NULL)//strchr返回pRight中首次出现c的位置
                    return false;
                //若不在pRight数组中,则表示当前假设为错误的,即c为(light)(轻/重)为错!
                break;
            case 'e':               //即even,若两边相等,即表示右边轻,那么假币c一定没有出现在两边数组中
                if (strchr(pLeft, c) || strchr(pRight, c))
                    return false;
                //若c存在于pLight或pRight数组中,则表示当前假设为错误的,即c为(light)(轻/重)为错!
                break;
            case 'd':               //即down,若右边下降,即表示右边重,那么假币c一定出现在天平的左边
                if (strchr(pLeft, c) == NULL)
                    return false;
                //若不在pLeft数组中,则表示当前假设为错误的,即c为(light)(轻/重)为错!
                break;
        }
    }
    return true;
}

第二题:完美立方式判断

Description

形如a^3=b^3+c^3+d^3的等式被称为完美立方等式。例如12^3=6^3+8^3+10^3。编写一个程序,对任给的正整数N(N≤100),寻找所有的四元组(a,b,c,d),使得a^3=b^3+c^3+d^3,其中1 < a,b,c,d ≤ N,且b ≤ c ≤ d。

Input

一个正整数N (N ≤ 100)。

Output

每行输出一个完美立方。输出格式为:Cube = a,Triple =(b,c,d)其中a,b,c,d所在位置分别用实际求出四元组值代入。

请按照a的值,从小到大依次输出。当两个完美立方等式中a的值相同,则b值小的优先输出、仍相同则c值小的优先输出、再相同则d值小的先输出。

Sample Input

24

Sample Output

Cube=6, Triple=(3,4,5)
Cube=12, Triple=(6,8,10)
Cube=18, Triple=(2,12,16)
Cube=18, Triple=(9,12,15)
Cube=19, Triple=(3,10,18)
Cube=20, Triple=(7,14,17)
Cube=24, Triple=(12,16,20)

该题较为简单,通过枚举所有情况即可求解。

采用四重循环枚举a,b,c,d,其中a在最外层,d在最里层,每一层都是从小到大枚举

为了减少不可能是正确解的枚举次数,应使

a的枚举范围为 [2,N];

b的枚举范围为 [2,a-1];

c的枚举范围为 [b,a-1];

d的枚举范围为 [c,a-1];

代码如下:

void PerfectCube(int N) {
    for (int a = 2; a <= N; ++a) {
        for (int b = 2; b < a; ++b) {
            for (int c = b; c < a; ++c) {
                for (int d = c; d < a; ++d) {
                    if (pow(a, 3) == pow(b, 3) + pow(c, 3) + pow(d, 3)) {
                        printf("Cube=%d, Triple=(%d,%d,%d)\n", a, b, c, d);
                    }
                }
            }
        }
    }
}

第三题:生理周期

Description

人有体力、情商、智商的高峰日子,它们分别每隔23天、28天和33天出现一次。对于每个人,我们想知道何时三个高峰落在同一天。给定三个高峰出现的日子physical,emotion和intelligence (不一定是第一次高峰出现的日子) 再给定另一个指定的日子day,你的任务是输出日子day之后,下一次三个高峰落在同一天的日子 (用距离day的天数表示)。例如: 给定日子为10,下次出现三个高峰同一天的日子是12,则输出2。

Input

输入四个整数:physical,emotion,intelligence和day。physical,emotion,intelligence分别表示体力、情感和智力高峰出现的日子。day是给定的日子,可能小于physical,emotion或intelligence。所有给定日子是非负的并且小于或等于365,所求的日子小于或等于21252。

Output

从给定日子day起,距离下一次体力、情感和智力高峰同一天的天数。

Sample Input

(0, 0, 0, 0)
(0, 0, 0, 100)
(5, 20, 34, 325)
(4, 5, 6, 7)
(283, 102, 23, 320)
(203, 301, 203, 40)

Sample Output

the next triple peak occurs in 21252 days.
the next triple peak occurs in 21152 days.
the next triple peak occurs in 19575 days.
the next triple peak occurs in 16994 days.
the next triple peak occurs in 8910 days.
the next triple peak occurs in 10789 days.

_

该题可以从day+1天开始,枚举至第21252天,对其中每一个日期count判断是否满足题中要求,即是否满足:

((count - physical) % 23 == 0 && (count - emotion) % 23 == 0 && (count - intelligence) % 23 == 0) 

但count的中由许多明显不满足题目条件的情况,

如:

  • 体力高峰到达一次后下次到达是在23天之后,所以要求满足体力高峰的情况下到达情感高峰的天数时count的递增步数应为23。
  • 同理当满足体力高峰、情感高峰日子的同时,求再满足智商高峰日子时,count的递增步数应为23、28的最小公倍数23*28。
  • 综上,按此方法跳着尝试判断count是否满足条件时,可以剪去很多明确的错解的分枝。

所以代码描述如下:

void CircadianCycle(int physical, int emotion, int intelligence, int day) {
    int count;
    for (count = day + 1; (count - physical) % 23; count++); //找到第一个体力高峰。
    for (; (count - emotion) % 28; count += 23);            //找到下一个体力、情感双高峰。
    for (; (count - intelligence) % 33; count += 23 * 28);     //在双高峰的基础上找到智力高峰,即为所求。
    printf("(%3d,%3d,%3d,%3d) -> the next triple peak occurs in %d days.\n", physical, emotion, intelligence, day,
           count - day);
}
  • 二三题的枚举方法在题目中体现的较为直观,第一题体现的并不直观,应详细分析后再枚举。
                                    by Ss1Two 2023/01/04
目录
相关文章
|
3月前
|
存储 监控 JavaScript
基于布隆过滤器的 Node.js 算法在局域网电脑桌面监控设备快速校验中的应用研究
本文探讨了布隆过滤器在局域网电脑桌面监控中的应用,分析其高效空间利用率、快速查询性能及动态扩容优势,并设计了基于MAC地址的校验模型,提供Node.js实现代码,适用于设备准入控制与重复数据过滤场景。
188 0
|
2月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
232 3
|
2月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
|
2月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
2月前
|
机器学习/深度学习 算法 安全
小场景大市场:猫狗识别算法在宠物智能设备中的应用
将猫狗识别算法应用于宠物智能设备,是AIoT领域的重要垂直场景。本文从核心技术、应用场景、挑战与趋势四个方面,全面解析这一融合算法、硬件与用户体验的系统工程。
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习模型、算法与应用的全方位解析
深度学习,作为人工智能(AI)的一个重要分支,已经在多个领域产生了革命性的影响。从图像识别到自然语言处理,从语音识别到自动驾驶,深度学习无处不在。本篇博客将深入探讨深度学习的模型、算法及其在各个领域的应用。
917 3
|
4月前
|
机器学习/深度学习 人工智能 算法
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
|
4月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
156 1
|
3月前
|
算法 数据可视化
matlab版本粒子群算法(PSO)在路径规划中的应用
matlab版本粒子群算法(PSO)在路径规划中的应用
|
4月前
|
存储 监控 算法
公司员工泄密防护体系中跳表数据结构及其 Go 语言算法的应用研究
在数字化办公中,企业面临员工泄密风险。本文探讨使用跳表(Skip List)数据结构优化泄密防护系统,提升敏感数据监测效率。跳表以其高效的动态数据处理能力,为企业信息安全管理提供了可靠技术支持。
122 0

热门文章

最新文章