枚举算法实例应用(一)

简介: 枚举算法实例应用,包括完美立方式判定、生理高峰问题、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
目录
相关文章
|
26天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
41 3
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的优化算法及其应用
【10月更文挑战第8天】 本文将探讨深度学习中常用的优化算法,包括梯度下降法、Adam和RMSProp等,介绍这些算法的基本原理与应用场景。通过实例分析,帮助读者更好地理解和应用这些优化算法,提高深度学习模型的训练效率与性能。
133 63
|
10天前
|
机器学习/深度学习 JSON 算法
二叉树遍历算法的应用场景有哪些?
【10月更文挑战第29天】二叉树遍历算法作为一种基础而重要的算法,在许多领域都有着不可或缺的应用,它为解决各种复杂的问题提供了有效的手段和思路。随着计算机科学的不断发展,二叉树遍历算法也在不断地被优化和扩展,以适应新的应用场景和需求。
19 0
|
21天前
|
存储 算法 搜索推荐
这些算法在实际应用中有哪些具体案例呢
【10月更文挑战第19天】这些算法在实际应用中有哪些具体案例呢
25 1
|
27天前
|
机器学习/深度学习 人工智能 算法
[大语言模型-算法优化] 微调技术-LoRA算法原理及优化应用详解
[大语言模型-算法优化] 微调技术-LoRA算法原理及优化应用详解
63 0
[大语言模型-算法优化] 微调技术-LoRA算法原理及优化应用详解
|
1月前
|
算法 安全 物联网
如何应用SM2算法进行身份认证
【10月更文挑战第5天】如何应用SM2算法进行身份认证
54 1
|
1月前
|
存储 算法 安全
SM2算法的应用场景有哪些?
【10月更文挑战第5天】SM2算法的应用场景有哪些?
64 1
|
1月前
|
存储 算法 安全
Python 加密算法详解与应用
Python 加密算法详解与应用
26 1
|
1月前
|
机器学习/深度学习 算法
深度学习中的优化算法及其应用
本文探讨了深度学习中常用的优化算法,包括梯度下降、随机梯度下降、动量方法和Adam方法。通过对比这些算法的优缺点及适用场景,帮助读者更好地理解和应用这些优化方法。
26 2
|
21天前
|
监控 算法 数据挖掘
HyperLogLog算法有哪些应用场景呢
【10月更文挑战第19天】HyperLogLog算法有哪些应用场景呢
14 0