文章目录
14、穷举
一、什么是穷举
穷举:列举所有的可能的数据,判断哪些数满足条件!
二、单循环穷举
1015:【入门】鸡兔同笼问题
思路:循环鸡可能的只数范围,看该范围内当鸡为多少只时是满足题目要求的!
//i代表鸡的总数
循环(鸡的只数范围i = 1~49){
如果(有i只鸡,有50-i只兔,腿的总数满足160){
输出鸡和兔的只数;
}
}
鸡 | 兔 | 腿 |
---|---|---|
1 | 49 | 1*2+49*4==160 |
2 | 48 | 2*2+48*4==160 |
3 | 47 | 3*2+47*4==160 |
4 | 50-i | i*2+(50)*4==160 |
49 | 1 | 49*2+1*4==160 |
/* 1015 - 【入门】鸡兔同笼问题
题目描述
鸡兔同笼问题:一个笼子里面有鸡若干只,兔若干只。共有头50个,共有腿160条。求鸡兔各多少只?(6.2.32)
输入
无
输出
两个整数,在一行。
鸡的只数 兔的只数 中间空格隔开!
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
//定义变量j,t分别代表鸡的只数和兔子的只数
int j,t;
for (j = 1; j <= 49; j++)
{
//兔子+鸡=50
t = 50 - j;
//当腿的数量=160,总只数=50,就输出j,t
if ((2 * j + 4 * t) == 160)
{
cout << j << " " << t << endl;
}
}
return 0;
}
1351:【入门】买公园门票
思路:循环(穷举)成人可能的人数范围,在有i个成人的情况下,买完成人票剩余的金
额如果是儿童票单价的倍数,说明该组数据是符合条件的。
穷举方法:
成人人数 | 剩余金额 | 方案是否可行? |
---|---|---|
1 | 40-1*8=36 | 32不是3的倍数,不可行 |
2 | 40-2*8=24 | 24是3的倍数,可行 |
… |
/* 1351 - 【入门】买公园门票
题目描述
某公园门票价格为:成人票8元/张,儿童票3元/张;某旅游团来公园游玩,该团内有成人和儿童(成人和儿童都有),共花了40元买门票,
请你分别计算出成人和儿童可能的人数,按照成人从少到多,儿童从多到少的规律数出结果。(7.2)
输入
无
输出
若干行,每行2个整数用空格隔开,分别代表成人和儿童可能的人数(成人从少到多,儿童从多到少)
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
/*
思路:
i =循环成人票可能的范围 1 ~ (40- 3) / 8
买了 i张成人票的情况下,剩余的钱必须是儿童票单价的倍数
*/
// i代表成人票的购买数量,x代表买了 i张成人票剩余的金额
int i, x;
//成人票最少1张,最多(40-3)/8张(因为至少留下买1张儿童票的钱)
for (i = 1; i <= (40 - 3) / 8; i++)
{
//计算剩余金额
x = 40 - i * 8;
if (x % 3 == 0)
{
cout << i << " " << x / 3 << endl;
}
}
}
1016:【入门】买小猫小狗
/* 1016 - 【入门】买小猫小狗
题目描述
某动物饲养中心用X元专款购买小狗(每只A元)和小猫(每只B元)两种小动物。
要求专款专用,(至少猫狗各一),正好用完。请求出方案的总数。如没有请输出0。
输入
输入一行,只有三个整数.分别为X,A,B. ( 100 < X < 32768; 1 <= A, B <= 100 )
输出
输出只有一行(这意味着末尾有一个回车符号),包括1个整数。
样例
输入复制
1700 31 21
输出复制
3
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
/*
共x元,小狗a元/只,小猫b元/只
至少猫狗各一,正好用完*/
int x, a, b, y, i; // y代表买了i只小狗剩余的钱
int c = 0; //计数的变量(count)
cin >> x >> a >> b;
//循环小狗可能的只数范围
for (i = 1; i <= (x - b) / a; i++)
{
//计算买了i只小狗剩余的金额
y = x - i * a;
//如果剩余的金额是小猫单价的倍数,则方案成立
if (y % b == 0)
{
// cout << i << " " << y / b << endl;
c = c + 1;
}
}
cout << c << endl;
}
代码中的y=x-i*a, 可以换成x=x-i*a吗
看看这样的解法:
//A狗单价,B猫单价,X金额
//循环小猫可能的只数
for(i=1;i<=(X-B)/A;i++){
//循环小狗可能的只数
for(j=1;j<=(X-A)/B;j++){
//判断购买小猫+小狗的钱是否正好等于X
if(A*i+B*j==X){
n++;
}
}
}
1227:【入门】阿凡提的难题
条件一:钱要花完
条件二:两种碗都要买
条件三:两种碗的数量都得是偶数
/* 1227 - 【入门】阿凡提的难题
题目描述
阿凡提去集市上买餐具,财主正好在卖餐具,所以准备为难一下阿凡提;
财主的餐具有2种:大碗和小碗,财主和阿凡提说,你买我的碗,要花光你带的钱,
而且,两种碗都要买,买的两种碗的数量都得是偶数,
请你编程帮助阿凡提计算,可以有哪些购买的方案呢?
输入
三个整数,分别代表了阿凡提带的钱的数量,大碗的价格,小碗的价格!
输出
所有的购买方案,一行一个方案,先输出大碗的采购只数,再输出小碗的采购只数!
样例
输入复制
100 20 10
输出复制
2 6
4 2
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
/* 花完所有的钱,两种碗都要买,两种碗的数量都是偶数 */
// q:阿凡提的总金额,x:买了 i只大碗剩余的钱
// big:大碗单价,small:小碗单价
int q, big, small, x, i;
cin >> q >> big >> small;
//循环大碗可能的只数范围(1~(q-2*small)/big)
for (i = 2; i <= (q - 2 * small) / big; i = i + 2)
{
//计算买了 i只大碗剩余的钱
x = q - i * big;
//如果剩余的钱是小碗单价的倍数,且买到小碗的数量是偶数
if (x % small == 0 && x / small % 2 == 0)
{
cout << i << " " << x / small << endl;
}
}
return 0;
}
四、可选作业
1349:【入门】植树的人数
1396:【入门】开学大采购
1394:【入门】恐龙园买玩具
1220:【入门】买糕点
五、嵌套循环穷举
1022:【入门】百钱百鸡问题
/* 1022 - 【入门】百钱百鸡问题
题目描述
用100元钱买100只鸡,公鸡,母鸡,小鸡都要有。公鸡5元1只,母鸡3元1只,小鸡1元3只。请问公鸡,母鸡,小鸡各应该买多少只?
输入
无
输出
每种买法占一行,由3个数组成,顺序为 公鸡数 母鸡数 小鸡数。每个数字空格隔开。
输出时,按公鸡数从少到多,母鸡数从多到少的顺序输出,本题符合条件的第一组解为:4 18 78。
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
int i, j, x, y;
//公鸡可能的只数范围
for (i = 1; i <= (100 - 3 - 1) / 5; i++)
{
//买完公鸡剩余的钱
x = 100 - i * 5;
//循环x元能买到的母鸡的范围
for (j = 1; j <= (x - 1) / 3; j++)
{
//买完i只公鸡,j只母鸡剩余的钱
y = x - j * 3;
if (i + j + y * 3 == 100)
{
cout << i << " " << j << " " << y * 3 << endl;
}
}
}
}
六、课堂练习
1025:【入门】兑换硬币
/* 1025 - 【入门】兑换硬币
题目描述
用一张一元票换1分、2分和5分的硬币,每种至少一枚, 问有几种换法?
输入
无
输出
输出只有一行(这意味着末尾有一个回车符号),包括1个整数。
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
/*
1元=10角=100分
循环1分可能的数量范围,用剩余的钱去换2分(循环2分数量范围)
*/
int i, j, x, y;
int c = 0; //计数器
//循环1分可能的数量范围
//循环1分可能的数量范围
for (i = 1; i <= 100 - 2 - 5; i++)
{
//换完1分剩余的钱
x = 100 - i;
//用×分去换2分
for (j = 1; j <= (x - 5) / 2; j++)
{
//计算换完1分和2分剩余的钱
y = x - j * 2;
//用y分去换5分
if (y % 5 == 0)
{
cout<<i<<" "<<j<<" "<<y/5<<endl;
c++;
}
}
}
cout << c << endl;
}
1024:【入门】购买文具
/* 1024 - 【入门】购买文具
题目描述
新学年就要开始了,爸爸把N元钱给了小青,让他购买一批文具,并作了以下要求:
只能买圆珠笔、铅笔和铅笔芯,并且每样至少买一支,总数要超过30支,而且钱要全部花完。
当小青去到文具店时,发现圆珠笔8角钱一支、铅笔2角钱一支、铅笔芯1角钱一支。
小青怎么买才能符合爸爸的要求呢?请你编个程序帮他算出符合购买要求的所有方案总数。
输入
一个整数N,表示购买文具一共的元数。(1 <= N <= 50)
输出
一个整数,即符合购买要求的所有方案总数。
样例
输入
8
输出
135
来源
需要找规律的循环
标签
需要找规律的循环 */
#include <bits/stdc++.h>
using namespace std;
int main()
{
/*
N元钱每样至少买一支总数要超过30支而且钱要全部花完
圆珠笔8角钱一支、铅笔2角钱一支、铅笔芯1角钱一支*/
int n, i, j, x, y;
int c = 0; //方案总数
cin >> n;
n = n * 10; //将单位元换算为角
//循环圆珠笔可能的购头数量范围
for (i = 1; i <= (n - 2 - 1) / 8; i++)
{
//计算买完圆珠笔剩余的钱
x = n - i * 8;
//用 x 角去购买铅笔
for (j = 1; j <= (x - 1) / 2; j++)
{
//计算买完圆珠笔和铅笔剩余的钱
y = x - j * 2;
//如果圆珠笔+铅笔+铅笔芯总数超过30支、
if (i + j + y > 30)
{
c++;
}
}
}
cout << c << endl;
}
七、作业
1249:【入门】搬砖问题
1250:【入门】马克思手稿的问题
1076:【入门】桐桐的计算
1342:【入门】怎样种树?
1077:【入门】桐桐去购物
八、规律类穷举
1251:【入门】四个人的年龄求解
1086:【入门】姐妹数对
1350:【入门】纸盒的最大体积是多少?
九、可选作业
1083:【基础】回文数
1013:【入门】一个六位数
1082:【入门】猴子吃桃子
代码参考:
https://gitee.com/huimutan/OI/tree/master/oj.czos.cn/basics