【NOI】C++算法设计入门之穷举


前言

穷举法是一种基础而实用的算法策略,它通过逐一检查所有可能的情况来寻找问题的解。这种方法特别适用于问题规模较小或解决方案数量有限的情况。尽管穷举法可能不是最高效的算法,但它保证能找到问题的正确答案,尤其适合于初学者理解和实践。

本章将介绍穷举法的基本概念、步骤以及通过几个具体的例子来演示如何使用穷举法解决问题。

学习路线:C++从入门到NOI学习路线

学习大纲:C++全国青少年信息学奥林匹克竞赛(NOI)入门级-大纲


一、概念

1.导入

今天我们要来学习穷举。

在这里插入图片描述

当然不是这个“穷举”啦,穷举法是一种基本的算法策略,它通过逐一检查所有可能的情况来寻找问题的解。

在这里插入图片描述

可能这么说,大家无法理解这个概念。

在这里插入图片描述

你有一个密码箱,密码是一个三位数,每一位都是从0到9的数字。

在这里插入图片描述

箱子里面有你想要用的东西,但是很巧的是你把密码忘记了。

这种情况下,我们怎样才能打开这个锁呢?

由于我们不知道密码是什么,那我们首先想要的方法就是尝试所有的可能性。也就是说,从000开始,一直试到999,总共有1000种可能的组合。

你们肯定不会想到下面这种方法的。

在这里插入图片描述

这种尝试000,如果不行,就尝试001;如果001也不行,就尝试002,以此类推;继续尝试,直到找到正确的密码为止的方法就是穷举法

2.概念

穷举法:通过尝试所有可能的选项来解决问题的方法。
优化:当有额外信息时,可以通过优化搜索范围来提高解决问题的效率。

穷举法的步骤如下:

  1. 确定问题的范围:根据问题的要求,确定需要尝试的数值范围。

  2. 使用循环进行穷举:使用循环结构(如for循环)遍历范围内的每个数值。

  3. 将数值带入问题中进行尝试:将当前数值带入问题中,判断是否满足问题的条件。

  4. 如果满足条件,输出结果或进行其他操作:如果当前数值满足问题的条件,可以输出该数值作为问题的解,或进行其他操作。

  5. 继续循环直到穷举完所有可能的解。

二、例题讲解

1. 简单穷举


问题:1015. 鸡兔同笼问题

类型:简单穷举


题目描述:

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

输入:

无。

输出:

两个整数,在一行。

鸡的只数 兔的只数。

中间空格隔开!

样例:

输入:


输出:


在这里插入图片描述


1.分析问题

  1. 已知:头50 个、腿有160个。
  2. 未知:鸡,兔各多少。
  3. 关系:鸡 头1腿2,兔 头1腿4。

2.定义变量

根据分析的已知,未知按需要定义变量。
j:鸡
t:兔

	//定义鸡、兔的数量。
	int j=0,t=0;

3.输入数据

无。

4.数据计算

4.1 确定问题的范围:根据问题的要求,确定需要尝试的数值范围。

t + j = 50,t * 2 + j * 4 = 140

4.2 使用循环进行穷举:使用循环结构(如for循环)遍历范围内的每个数值。

4.3 将数值带入问题中进行尝试:将当前数值带入问题中,判断是否满足问题的条件。

//四、数据计算 
	while(j*2+(50-j)*4!=160){
   
		j++;
	} 
	

4.4 如果满足条件,输出结果或进行其他操作。

t=50-j;
cout<<j<<" "<<t<<endl;

完整代码如下:

#include<iostream>
using namespace std;

int main(){
   
    // 一、分析问题
    // 已知:笼子里有50只动物(鸡和兔),这些动物总共有160条腿。
    // 未知:鸡和兔各有多少只?

    // 二、数据定义
    // 定义鸡、兔的数量。
    int j = 0, t = 0;
    
    // 三、数据输入
    // (在这个简单的示例中,数据已经作为常量给出,无需用户输入)

    // 四、数据计算
    // 使用while循环来穷举所有可能的鸡的数量
    // 每次循环增加鸡的数量,并检查当前的腿总数是否等于160
    while (j * 2 + (50 - j) * 4 != 160) {
   
        j++;  // 增加鸡的数量
    } 
    t = 50 - j;  // 兔子的数量为总数减去鸡的数量
    
    // 五、输出结果
    cout << j << " " << t << endl;  // 输出鸡和兔的数量

    return 0;  // 主函数结束,返回0表示程序正常退出
}


欢迎关注本专栏《C++从零基础到信奥赛入门级(CSP-J)》

问题:1351. 买公园门票

类型:简单穷举


题目描述:

某公园门票价格为:成人票 8 元 / 张,儿童票 3 元 / 张;某旅游团来公园游玩,该团内有成人和儿童(成人和儿童都有),共花了 40 元买门票。

请你分别计算出成人和儿童可能的人数,按照成人从少到多,儿童从多到少的规律数出结果。

输入:

输出:

若干行,每行 2 个整数用空格隔开,分别代表成人和儿童可能的人数。(成人从少到多,儿童从多到少)

样例:

输入:


输出:


在这里插入图片描述


1.分析问题

  1. 已知:成人票 8 元 / 张,儿童票 3 元 / 张;共花了 40 元买门票。
  2. 未知:成人和儿童的人数。
  3. 关系:成人从少到多,儿童从多到少。

2.定义变量

无。

3.输入数据

无。

4.数据计算

4.1 确定问题的范围:根据问题的要求,确定需要尝试的数值范围。

成人票:最少1张,最多(40-3)/8张,要保证有一张儿童票。
儿童票:最少1张,最多(40-8)/3张,要保证有一张成人票。

4.2 使用循环进行穷举:使用循环结构(如for循环)遍历范围内的每个数值。

i:成人票数量。

for(int i=1;i<=(40-3)/8;i++){
   
	
	}

4.3 将数值带入问题中进行尝试:将当前数值带入问题中,判断是否满足问题的条件。

j:购买成人票后剩余钱数。

如果j%3==0,说明剩余的钱刚好能买整数个儿童票,符合题意。

//四、数据计算 
	for(int i=1;i<=(40-3)/8;i++){
   
		int j=40-8*i;
		if(j%3==0){
   
		}
		
	}
	

4.4 如果满足条件,输出结果或进行其他操作。如果当前数值满足问题的条件,可以输出该数值作为问题的解,或进行其他操作。

//四、数据计算 
	for(int i=1;i<=(40-3)/8;i++){
   
		int j=40-8*i;
		if(j%3==0){
   
			//五、输出结果 
			cout<<i<<" "<<j/3;
		}
		
	}

4.5 继续循环直到穷举完所有可能的解。

完整代码如下:

#include<iostream>
using namespace std;

int main(){
   
    // 一、分析问题
    // 1. 已知:成人票 8 元 / 张,儿童票 3 元 / 张;共花了 40 元买门票。
    // 2. 未知:成人和儿童的人数。

    // 二、数据定义
    // 定义成人票和儿童票的数量。
    // 由于成人票价较高,我们从成人票开始穷举。

    // 三、数据输入
    // (在这个简单的示例中,数据已经作为常量给出,无需用户输入)

    // 四、数据计算
    // 使用for循环来穷举所有可能的成人票数量
    // 每次循环增加成人票的数量,并检查剩余金额是否能被3整除
    for(int i = 1; i <= (40 - 3) / 8; i++) {
     // 穷举成人票数量
        int j = 40 - 8 * i;  // 剩余金额
        if (j % 3 == 0) {
     // 如果剩余金额能被3整除
            // 五、输出结果
            cout << i << " " << j / 3 << endl;  // 输出成人和儿童的人数
        }
    }

    return 0;  // 主函数结束,返回0表示程序正常退出
}

欢迎关注本专栏《C++从零基础到信奥赛入门级(CSP-J)》

问题:1016. 买小猫小狗

类型:简单循环


题目描述:

某动物饲养中心用 X 元专款购买小狗(每只 A 元)和小猫(每只B 元)两种小动物。

要求专款专用,(至少猫狗各一),正好用完。

请求出方案的总数。如没有请输出 0 。

输入:

输入一行,只有三个整数.分别为 X,A,B。( 100<X<32768,1≤A≤100,1≤B≤100 )

输出:

输出只有一行(这意味着末尾有一个回车符号),包括 1 个整数。

样例:

输入:

1700 31 21

输出:

3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

明月别枝惊鹊丶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值