什么是穷举法
穷举法(Brute Force Method)是一种通过尝试所有可能的解决方案来找到满足条件的解的方法。虽然这种方法比较简单直接,但当可能的解非常多时,穷举法的效率会较低。
穷举法的基本结构
穷举法的基本结构可以概括为以下几个步骤:
- 定义解空间:明确所有可能的解。
- 遍历解空间:使用循环遍历所有可能的解。
- 检查每一个解:判断当前解是否满足问题的条件。
- 记录或输出符合条件的解:如果找到符合条件的解,记录或输出它。
基本结构的代码模板
#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 条。求鸡兔各多少只?
解题思路
可以采用穷举法来解决这个问题。穷举法的基本思路是:遍历所有可能的鸡的数量,然后计算相应的兔的数量,验证这些数量是否满足腿的总数。如果满足条件,则输出结果。
- 遍历鸡的数量:鸡的数量从0到50进行遍历。
- 计算兔的数量:根据总头数50,兔的数量可以通过
50 - 鸡的数量
来计算。 - 验证条件:计算对应的腿的总数是否等于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; 定义两个整型变量
x
和y
分别存储鸡和兔的数量。 - 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到4进行遍历。
- 计算儿童的数量:根据总花费减去成人票的花费来计算儿童的数量。
- 验证条件:检查剩余的钱数能否被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到
x / a
,因为购买至少一只小狗。 - 验证条件:对于每一种可能的小狗数量,计算剩余的钱数是否能被小猫的价格
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; 定义三个整型变量
x
、a
、b
分别存储专款金额、小狗价格和小猫价格。 - 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开始遍历,计算剩余的钱数。
- 计算剩余的钱数能否被面包的价格整除:如果能整除,则输出此方案,表示最多的面包数量和对应的蛋挞数量。
代码实现
#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; 定义三个整型变量
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; 找到方案后直接退出循环。
这样,程序能够正确计算并输出能够买到最多面包的最佳方案。
1227. 阿凡提的难题
问题描述
阿凡提去集市上买餐具,财主正好在卖餐具,所以准备为难一下阿凡提。
财主的餐具有 2 种:大碗和小碗,财主和阿凡提说,你买我的碗,要花光你带的钱,而且,两种碗都要买,买的两种碗的数量都得是偶数。
请你编程帮助阿凡提计算,可以有哪些购买的方案呢?
输入
输入为三个整数,分别代表阿凡提带的钱的数量、大碗的价格、小碗的价格。
输出
输出所有符合条件的购买方案,一行一个方案,先输出大碗的采购只数,再输出小碗的采购只数。
解题思路
这道题的要求是找出符合以下条件的所有购买方案:
- 花光所有的钱:购买的碗的总花费等于阿凡提带的钱。
- 两种碗都要买:大碗和小碗的数量都必须大于0。
- 数量为偶数:大碗和小碗的数量都必须是偶数。
我们可以通过穷举法来遍历大碗的数量,然后计算相应的小碗数量,看是否符合上述条件。
代码实现
#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到甲组的总人数(17人)依次遍历。
- 验证条件:检查抽调后乙组的人数是否等于甲组人数的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开始到能购买的最多篮球数量。
- 计算排球数量:根据剩余的经费计算可购买的排球数量。
- 验证条件:检查是否满足总经费用完、总数量超过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; 定义三个整型变量
n
、x
、y
分别存储总经费、篮球单价和排球单价。 - 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元钞票数量,看是否满足条件。具体步骤如下:
- 遍历10元钞票的数量:从1到10元面额的最大数量(100/10 = 10)。
- 计算剩余金额:剩余金额用于换取20元钞票。
- 验证条件:剩余金额是否能够被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)。
输出
一个整数,代表购买方案的总数。
解题思路
我们可以通过穷举法来解决这个问题:
- 遍历苹果的数量:从10斤到最多能购买的苹果数量 (n/x)。
- 计算剩余金额:用剩余的金额去购买梨。
- 验证条件:剩余的金额是否能够被梨的单价整除,并且梨的购买数量是否大于等于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; 定义三个整型变量
n
、x
、y
分别存储总金额、苹果的单价和梨的单价。 - 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到最大能购买的霸王龙数量 (n/x)。
- 计算剩余金额:用剩余的钱去购买三角龙。
- 验证条件:剩余的钱能否购买整件三角龙,总数是否大于等于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; 定义三个整型变量
n
、x
、y
分别存储总金额、霸王龙的单价和三角龙的单价。 - 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; 输出符合条件的霸王龙和三角龙数量。
该程序能够正确计算并输出所有符合条件的购买方案。