9、穷举算法-逐一尝试法 - 课件

什么是穷举法

穷举法(Brute Force Method)是一种通过尝试所有可能的解决方案来找到满足条件的解的方法。虽然这种方法比较简单直接,但当可能的解非常多时,穷举法的效率会较低。

穷举法的基本结构

穷举法的基本结构可以概括为以下几个步骤:

  1. 定义解空间:明确所有可能的解。
  2. 遍历解空间:使用循环遍历所有可能的解。
  3. 检查每一个解:判断当前解是否满足问题的条件。
  4. 记录或输出符合条件的解:如果找到符合条件的解,记录或输出它。

基本结构的代码模板

#include <iostream>
using namespace std;

int main() {
    // Step 1: 定义解空间(例如遍历范围)
    int N = 10; // 设定解空间大小为10

    // Step 2: 遍历解空间
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            // Step 3: 检查每一个解是否满足条件
            if (i + j == N) {
                // Step 4: 记录或输出符合条件的解
                cout << "找到符合条件的组合: " << i << " + " << j << " = " << N << endl;
            }
        }
    }

    return 0;
}

穷举法的例子

问题描述

假设我们要找到两个正整数的组合,使得它们的和等于一个给定的数。例如,给定一个数10,找出所有满足a + b = 10的正整数对(a, b)

代码实现

#include <iostream>
using namespace std;

int main() {
    int 目标和 = 10; // 定义目标和

    // 遍历所有可能的a值
    for (int a = 1; a < 目标和; a++) {
        // 遍历所有可能的b值
        for (int b = 1; b < 目标和; b++) {
            // 检查a和b的和是否等于目标和
            if (a + b == 目标和) {
                // 输出符合条件的a和b
                cout << "找到符合条件的组合: (" << a << ", " << b << ")" << endl;
            }
        }
    }

    return 0;
}

输出结果

找到符合条件的组合: (1, 9)
找到符合条件的组合: (2, 8)
找到符合条件的组合: (3, 7)
找到符合条件的组合: (4, 6)
找到符合条件的组合: (5, 5)
找到符合条件的组合: (6, 4)
找到符合条件的组合: (7, 3)
找到符合条件的组合: (8, 2)
找到符合条件的组合: (9, 1)

在这个例子中,穷举法遍历了所有可能的整数对(a, b),并输出了满足a + b = 10的所有组合。通过遍历所有可能的值,我们找到并展示了所有符合条件的解。

1015. 鸡兔同笼问题

问题描述

鸡兔同笼问题:一个笼子里面有鸡若干只,兔若干只。共有头 50 个,共有腿 160 条。求鸡兔各多少只?

解题思路

可以采用穷举法来解决这个问题。穷举法的基本思路是:遍历所有可能的鸡的数量,然后计算相应的兔的数量,验证这些数量是否满足腿的总数。如果满足条件,则输出结果。

  1. 遍历鸡的数量:鸡的数量从0到50进行遍历。
  2. 计算兔的数量:根据总头数50,兔的数量可以通过50 - 鸡的数量来计算。
  3. 验证条件:计算对应的腿的总数是否等于160,如果是,则输出当前的鸡和兔的数量。
代码实现
#include <iostream>
using namespace std;

int main() {
    int x, y; // 定义变量存储鸡和兔的数量

    // 穷举所有可能的鸡的数量
    for (x = 0; x <= 50; x++) {
        y = 50 - x; // 根据总头数计算兔的数量
        if (2 * x + 4 * y == 160) { // 验证腿的总数是否满足条件
            cout << x << " " << y << endl; // 输出符合条件的鸡和兔的数量
            break; // 找到符合条件的解后,退出循环
        }
    }

    return 0; // 程序结束
}
代码解析
  • int x, y; 定义两个整型变量xy分别存储鸡和兔的数量。
  • for (x = 0; x <= 50; x++) 遍历所有可能的鸡的数量,范围从0到50。
  • y = 50 - x; 根据总头数计算对应的兔的数量。
  • if (2 * x + 4 * y == 160) 验证当前鸡和兔的数量对应的腿的总数是否等于160。
  • cout << x << " " << y << endl; 如果条件满足,则输出当前的鸡和兔的数量,并用空格分隔。
  • break; 找到符合条件的解后,立即退出循环,防止多次输出。

通过穷举法,这段代码可以正确计算并输出鸡和兔的数量。

1351. 买公园门票

问题描述

某公园门票价格为:成人票 8 元 / 张,儿童票 3 元 / 张;某旅游团来公园游玩,该团内有成人和儿童(成人和儿童都有),共花了 40 元买门票。
请你分别计算出成人和儿童可能的人数,按照成人从少到多,儿童从多到少的规律数出结果。

解题思路

该问题可以通过穷举法来解决。穷举法的基本思路是:遍历所有可能的成人数量,然后根据剩余的钱数计算出相应的儿童数量,验证这些数量是否符合总花费40元的条件。如果满足条件,则输出成人和儿童的数量。

  1. 遍历成人的数量:成人的数量从1到4进行遍历。
  2. 计算儿童的数量:根据总花费减去成人票的花费来计算儿童的数量。
  3. 验证条件:检查剩余的钱数能否被3整除,如果是,则输出结果。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int i = 0; // 定义变量存储成人的数量

    // 穷举所有可能的成人数量
    for(i = 1; i < 5; i++) // 成人的数量从1到4
    {
        // 计算剩余的钱数是否刚好够小孩的票价
        if((40 - (i * 8)) % 3 == 0) // 如果除了大人的门票外,剩下的钱刚好够小孩门票的钱
        {
            cout << i << " " << (40 - (i * 8)) / 3 << endl; // 输出符合条件的成人和儿童数量
        } 
    } 
    return 0; // 程序结束
}
代码解析
  • int i = 0; 定义一个整型变量i来存储成人的数量。
  • for(i = 1; i < 5; i++) 遍历所有可能的成人数量,范围从1到4。
  • if((40 - (i * 8)) % 3 == 0) 检查剩余的钱数是否可以被3整除,即能否刚好够买儿童票。
  • cout << i << " " << (40 - (i * 8)) / 3 << endl; 如果条件满足,输出当前的成人和儿童数量,并用空格分隔。

这样,程序能够正确计算并输出符合条件的成人和儿童数量,结果按照成人从少到多,儿童从多到少的顺序输出。

1016. 买小猫小狗

问题描述

某动物饲养中心用 X 元专款购买小狗(每只 A 元)和小猫(每只 B 元)两种小动物。
要求专款专用,(至少猫狗各一),正好用完。
请求出方案的总数。如没有请输出 0。

解题思路

该问题可以通过穷举法来解决。穷举法的基本思路是:遍历所有可能的小狗的数量,然后计算剩余的钱数能否被小猫的价格整除。如果能整除,则表示当前方案可行,方案数加一。

  1. 遍历小狗的数量:小狗的数量从1到x / a,因为购买至少一只小狗。
  2. 验证条件:对于每一种可能的小狗数量,计算剩余的钱数是否能被小猫的价格b整除。如果可以,则方案数加一。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int x, a, b;
    cin >> x >> a >> b; // 输入专款金额、小狗价格和小猫价格
    
    int num = 0; // 统计符合条件的方案数
    
    int dog;
    for(dog = 1; dog < (x / a); dog++) // 小狗的数量从1开始,最大不超过 x / a
    {
        if(((x - (dog * a)) % b) == 0) // 判断剩余的钱数是否能被小猫的价格整除
        {
            num++; // 如果可以,则方案数加一
        }
    } 
    cout << num << endl; // 输出符合条件的方案总数
    return 0; // 程序结束
}
代码解析
  • int x, a, b; 定义三个整型变量xab分别存储专款金额、小狗价格和小猫价格。
  • cin >> x >> a >> b; 从标准输入中读取专款金额、小狗价格和小猫价格。
  • int num = 0; 定义一个变量num用于统计符合条件的方案数。
  • for(dog = 1; dog < (x / a); dog++) 遍历小狗的数量,范围从1到x / a
  • if(((x - (dog * a)) % b) == 0) 验证剩余的钱数是否能被小猫的价格整除。
  • num++; 如果条件满足,则方案数加一。
  • cout << num << endl; 最后输出符合条件的方案总数。

这样,程序能够正确计算并输出符合条件的购买方案数。如果没有符合条件的方案,结果将为0。

1220. 买糕点

问题描述

妈妈给了小明 (n) 元去面包店买糕点,小明想花光这 (n) 元买切片面包和蛋挞,而且每样至少买一件。小明想知道,能够买最多面包的方案是什么?

输入

输入为三个整数,分别代表总金额 (n),面包的单价 (x) 和蛋挞的单价 (y)。

输出

输出两个整数,分别代表能够买到最多面包的件数和相应的蛋挞件数。

解题思路

为了找到能够买到最多面包的方案,我们可以通过以下步骤解决:

  1. 遍历蛋挞的数量:从1开始遍历,计算剩余的钱数。
  2. 计算剩余的钱数能否被面包的价格整除:如果能整除,则输出此方案,表示最多的面包数量和对应的蛋挞数量。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int n, x, y;
    cin >> n >> x >> y; // 输入总金额、面包的单价和蛋挞的单价

    for(int i = 1; i <= (n - i * y); i++) // 从1开始遍历蛋挞的数量
    {
        int j = n - i * y; // 计算剩余的钱数,即买面包的钱
        if(j % x == 0) // 如果剩余的钱数能够买整件面包
        {
            cout << j / x << " " << i; // 输出最多面包的数量和蛋挞的数量
            break; // 找到方案后直接退出循环
        }
    }
    return 0; // 程序结束
}
代码解析
  • int n, x, y; 定义三个整型变量nxy分别存储总金额、面包的单价和蛋挞的单价。
  • cin >> n >> x >> y; 从标准输入中读取这些数据。
  • for(int i = 1; i <= (n - i * y); i++) 从1开始遍历蛋挞的数量,计算剩余的钱数是否能买整件面包。
  • int j = n - i * y; 计算剩余的钱数,即买面包的钱。
  • if(j % x == 0) 检查剩余的钱数能否被面包的价格整除。
  • cout << j / x << " " << i; 输出最多面包的数量和相应的蛋挞数量。
  • break; 找到方案后直接退出循环。

这样,程序能够正确计算并输出能够买到最多面包的最佳方案。

1227. 阿凡提的难题

问题描述

阿凡提去集市上买餐具,财主正好在卖餐具,所以准备为难一下阿凡提。
财主的餐具有 2 种:大碗和小碗,财主和阿凡提说,你买我的碗,要花光你带的钱,而且,两种碗都要买,买的两种碗的数量都得是偶数。
请你编程帮助阿凡提计算,可以有哪些购买的方案呢?

输入

输入为三个整数,分别代表阿凡提带的钱的数量、大碗的价格、小碗的价格。

输出

输出所有符合条件的购买方案,一行一个方案,先输出大碗的采购只数,再输出小碗的采购只数。

解题思路

这道题的要求是找出符合以下条件的所有购买方案:

  1. 花光所有的钱:购买的碗的总花费等于阿凡提带的钱。
  2. 两种碗都要买:大碗和小碗的数量都必须大于0。
  3. 数量为偶数:大碗和小碗的数量都必须是偶数。

我们可以通过穷举法来遍历大碗的数量,然后计算相应的小碗数量,看是否符合上述条件。

代码实现
#include "iostream"
using namespace std;

int main()
{
    int total_money, big_bowl_price, small_bowl_price;
    cin >> total_money >> big_bowl_price >> small_bowl_price; // 输入带的钱的数量、大碗的价格、小碗的价格
    
    for(int big_bowls = 2; big_bowls <= total_money / big_bowl_price; big_bowls += 2) // 遍历大碗的数量,从2开始,步长为2
    {
        int remaining_money = total_money - big_bowls * big_bowl_price; // 计算剩余的钱数
        if(remaining_money > 0 && remaining_money % small_bowl_price == 0) // 剩余的钱数是否可以用来买小碗
        {
            int small_bowls = remaining_money / small_bowl_price; // 计算小碗的数量
            if(small_bowls > 0 && small_bowls % 2 == 0) // 小碗的数量也必须是偶数
            {
                cout << big_bowls << " " << small_bowls << endl; // 输出符合条件的大碗和小碗数量
            }
        }
    }

    return 0; // 程序结束
}
代码解析
  • int total_money, big_bowl_price, small_bowl_price; 定义三个整型变量,分别存储阿凡提带的钱的数量、大碗的价格、小碗的价格。
  • cin >> total_money >> big_bowl_price >> small_bowl_price; 从标准输入读取这些数据。
  • for(int big_bowls = 2; big_bowls <= total_money / big_bowl_price; big_bowls += 2) 遍历大碗的数量,从2开始,步长为2(保证大碗的数量是偶数)。
  • int remaining_money = total_money - big_bowls * big_bowl_price; 计算剩余的钱数。
  • if(remaining_money > 0 && remaining_money % small_bowl_price == 0) 判断剩余的钱数是否能整除小碗的价格,并且剩余的钱数要大于0。
  • int small_bowls = remaining_money / small_bowl_price; 计算小碗的数量。
  • if(small_bowls > 0 && small_bowls % 2 == 0) 判断小碗的数量是否大于0且为偶数。
  • cout << big_bowls << " " << small_bowls << endl; 输出符合条件的购买方案。

该程序能够正确计算并输出所有符合条件的购买方案。

1349. 植树的人数

问题描述

某班学生分2组参加植树活动,甲组有17人,乙组有25人。后来由于需要,从甲组抽调了部分学生去乙组,结果乙组的人数是甲组的2倍。请问从甲组抽调了多少人去乙组?

输入

输出

输出甲组抽调去乙组的人数。

解题思路

通过遍历从甲组抽调的学生人数,逐一检查是否满足乙组人数是甲组人数的2倍的条件。具体步骤如下:

  1. 遍历可能的抽调人数:从1到甲组的总人数(17人)依次遍历。
  2. 验证条件:检查抽调后乙组的人数是否等于甲组人数的2倍。
代码实现
#include "iostream"
using namespace std;

int main() {
    int a = 17, b = 25; // 甲组和乙组的初始人数
    for(int i = 1; i <= a; i++) // 遍历可能的抽调人数
    {
        if(2 * (a - i) == (b + i)) // 检查抽调后是否满足乙组人数是甲组人数的2倍
        {
            cout << i; // 输出符合条件的抽调人数
            break; // 找到结果后退出循环
        }
    }
    return 0; // 程序结束
}
代码解析
  • int a = 17, b = 25; 初始化甲组和乙组的学生人数。
  • for(int i = 1; i <= a; i++) 遍历可能的抽调人数,从1开始到甲组的总人数(17)。
  • if(2 * (a - i) == (b + i)) 判断抽调后乙组的人数是否为甲组人数的2倍。
  • cout << i; 输出符合条件的抽调人数。
  • break; 找到满足条件的结果后,立即退出循环,避免多次输出。

这个程序可以正确计算并输出从甲组抽调到乙组的学生人数。

1396. 开学大采购

问题描述

新学期开始了,学校计划采购一批新的篮球和排球用来上体育课。学校共有 (n) 元经费,篮球 (x) 元/个,排球 (y) 元/个。现要求篮球和排球都至少采购 1 个,且 (n) 元经费全部用完,篮球和排球的总数要超过 50 个。请问有哪些采购方案?(按照篮球从少到多,排球从多到少输出所有可行的方案)

输入

输入为三个整数,分别代表总经费 (n)、篮球单价 (x)、排球单价 (y)。

输出

输出所有可行的采购方案,每个组方案有 2 个整数用空格隔开,第 1 个整数代表篮球的采购个数,第 2 个整数代表排球的采购个数。

解题思路

通过遍历可能的篮球采购数量,计算对应的排球数量,看是否满足所有条件:经费正好用完,总数量超过50个,并且篮球和排球都至少有一个。

  1. 遍历篮球数量:从1开始到能购买的最多篮球数量。
  2. 计算排球数量:根据剩余的经费计算可购买的排球数量。
  3. 验证条件:检查是否满足总经费用完、总数量超过50个,以及篮球和排球都至少1个的要求。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int n, x, y;
    cin >> n >> x >> y; // 输入总经费、篮球单价、排球单价
    
    for(int i = 1; i <= (n / x); i++) // 遍历篮球的数量
    {
        int j = n - i * x; // 计算剩余的钱,即买排球的钱
        if(j % y == 0 && j > 0 && (i + (j / y) > 50)) // 检查剩余的钱能否买整件排球且总数超过50
        {
            cout << i << " " << (j / y) << endl; // 输出符合条件的方案
        }
    }
    return 0; // 程序结束
}
代码解析
  • int n, x, y; 定义三个整型变量nxy分别存储总经费、篮球单价和排球单价。
  • cin >> n >> x >> y; 从标准输入中读取这些数据。
  • for(int i = 1; i <= (n / x); i++) 遍历篮球的数量,从1到最多的篮球数量。
  • int j = n - i * x; 计算剩余的钱数,即用于购买排球的金额。
  • if(j % y == 0 && j > 0 && (i + (j / y) > 50)) 检查剩余的钱数是否能够买整件排球,并且总数是否超过50个。
  • cout << i << " " << (j / y) << endl; 输出符合条件的采购方案。

这个程序可以正确计算并输出所有符合条件的采购方案,方案按照篮球从少到多,排球从多到少的顺序输出。

1792. 换钞票

问题描述

将一张100元的钞票换成10元和20元两种面额的钞票,两种不同的面额都要有,有哪些不同的换法。请按照10元面额的数量由小到大,20元面额的数量由大到小输出所有的结果。

输入

输出

输出满足条件的方案,每行2个整数,第1个整数代表10元面额的数量,第2个整数代表20元面额的数量。输出时按照10元面额数量从小到大,20元面额数量从大到小输出。

解题思路

通过遍历可能的10元钞票的数量,计算对应的20元钞票数量,看是否满足条件。具体步骤如下:

  1. 遍历10元钞票的数量:从1到10元面额的最大数量(100/10 = 10)。
  2. 计算剩余金额:剩余金额用于换取20元钞票。
  3. 验证条件:剩余金额是否能够被20整除,并且两种面额都至少有一张。
代码实现
#include "iostream"
using namespace std;

int main()
{
    for(int i = 1; i <= (100 / 10); i++) // 遍历10元面额的数量
    {
        int j = (100 - i * 10); // 计算剩余的金额
        if(j % 20 == 0 && j > 0) // 判断剩余的钱数能否换成20元面额且剩余金额大于0
        {
            cout << i << " " << j / 20 << endl; // 输出10元和20元的数量
        }
    }
    return 0; // 程序结束
}
代码解析
  • for(int i = 1; i <= (100 / 10); i++) 遍历10元面额的数量,从1开始,直到最多10张。
  • int j = (100 - i * 10); 计算剩余的金额,即100元减去i张10元钞票的金额。
  • if(j % 20 == 0 && j > 0) 检查剩余的金额是否能被20整除,且剩余金额要大于0(确保20元面额有至少一张)。
  • cout << i << " " << j / 20 << endl; 输出符合条件的方案,每行输出一对整数,分别代表10元和20元的数量。

这样,程序能够正确计算并输出所有符合条件的换钞方案,方案按照10元面额数量从小到大,20元面额数量从大到小的顺序输出。

1793. 采购水果

问题描述

食堂采购员用 (n) 元去水果市场采购苹果和梨,已知苹果 (x) 元/斤,梨 (y) 元/斤,要求每种水果都至少购买到 10 斤或 10 斤以上,且要把 (n) 元花完,请问有多少种不同的买法?

输入

输入为三个整数,分别代表总金额 (n)、苹果的单价 (x) 和梨的单价 (y)。

输出

一个整数,代表购买方案的总数。

解题思路

我们可以通过穷举法来解决这个问题:

  1. 遍历苹果的数量:从10斤到最多能购买的苹果数量 (n/x)。
  2. 计算剩余金额:用剩余的金额去购买梨。
  3. 验证条件:剩余的金额是否能够被梨的单价整除,并且梨的购买数量是否大于等于10斤。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int n, x, y;
    cin >> n >> x >> y; // 输入总金额、苹果单价和梨单价

    int num = 0; // 统计符合条件的方案数
    for(int i = 10; i <= (n / x); i++) // 遍历苹果的数量,从10斤开始
    {
        int j = n - i * x; // 计算剩余的钱数
        if(j > 0 && j % y == 0 && (j / y) >= 10) // 判断剩余的钱是否能买整件梨且不少于10斤
        {
            num++; // 符合条件的方案数加一
        }
    }
    cout << num; // 输出总的购买方案数
    return 0; // 程序结束
}
代码解析
  • int n, x, y; 定义三个整型变量nxy分别存储总金额、苹果的单价和梨的单价。
  • cin >> n >> x >> y; 从标准输入中读取这些数据。
  • int num = 0; 定义变量num用于统计符合条件的方案数。
  • for(int i = 10; i <= (n / x); i++) 遍历苹果的数量,从10斤开始,最大值为(n/x)。
  • int j = n - i * x; 计算剩余的金额。
  • if(j > 0 && j % y == 0 && (j / y) >= 10) 判断剩余的钱数能否购买整件梨且不少于10斤。
  • num++; 符合条件的方案数加一。
  • cout << num; 输出符合条件的购买方案总数。

这个程序可以正确计算并输出所有符合条件的购买方案数量。

1394. 恐龙园买玩具

问题描述

小明暑假来到恐龙园游玩,想购买霸王龙和三角龙玩偶送给自己的5位好朋友。霸王龙玩偶一只需要 (x) 元,三角龙玩偶一只需要 (y) 元。小明有 (n) 元,希望两种恐龙都能购买,且购买的霸王龙数量要大于或等于三角龙数量,总数要在5个或以上,并且不能有钱剩下。请输出所有可能的购买方案。

输入

输入为三个整数,分别代表总金额 (n)、霸王龙的单价 (x) 和三角龙的单价 (y)。

输出

输出所有满足条件的购买方案,每组购买方案占1行,用空格隔开2个数,分别代表霸王龙的数量和三角龙的数量。

解题思路
  1. 遍历霸王龙的数量:从1到最大能购买的霸王龙数量 (n/x)。
  2. 计算剩余金额:用剩余的钱去购买三角龙。
  3. 验证条件:剩余的钱能否购买整件三角龙,总数是否大于等于5个,且霸王龙数量大于或等于三角龙数量。
代码实现
#include "iostream"
using namespace std;

int main()
{
    int n, x, y;
    cin >> n >> x >> y; // 输入总金额、霸王龙单价和三角龙单价
    
    for(int i = 1; i <= (n / x); i++) // 遍历霸王龙的数量
    {
        int j = n - i * x; // 计算剩余的钱数
        if(j % y == 0 && j > 0 && (j / y) + i >= 5 && i >= (j / y)) // 验证条件
        {
            cout << i << " " << j / y << endl; // 输出满足条件的方案
        }
    }
    return 0; // 程序结束
}
代码解析
  • int n, x, y; 定义三个整型变量nxy分别存储总金额、霸王龙的单价和三角龙的单价。
  • cin >> n >> x >> y; 从标准输入中读取这些数据。
  • for(int i = 1; i <= (n / x); i++) 遍历可能购买的霸王龙数量,从1开始,直到最大可能数量。
  • int j = n - i * x; 计算剩余的钱数,用于购买三角龙。
  • if(j % y == 0 && j > 0 && (j / y) + i >= 5 && i >= (j / y)) 判断剩余的钱数能否整除三角龙的单价,且满足总数大于等于5个,并且霸王龙数量要大于或等于三角龙数量。
  • cout << i << " " << j / y << endl; 输出符合条件的霸王龙和三角龙数量。

该程序能够正确计算并输出所有符合条件的购买方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天秀信奥编程培训

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

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

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

打赏作者

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

抵扣说明:

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

余额充值