百钱买百鸡(枚举思想编写,并进行3次优化)

9 篇文章 0 订阅
6 篇文章 0 订阅

1.题目

我国古代数学家张丘建在《算经》一书中曾提出著名的“百钱买百鸡”问题:鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一;百钱买百鸡,则翁、母、雏各几何?
翻译过来,意思是公鸡一个五块钱,母鸡一个三块钱,小鸡三个一块钱,问公鸡、母鸡、小鸡各多少只?

2.枚举法思想解法

2.1 枚举法思路

  • 枚举变量:公鸡,母鸡,小鸡对应了i,j,k
  • 枚举范围:公鸡,母鸡,小鸡都是1-100次,对应了i,j,k分别循环一百次
  • 枚举判断条件:
    • 钱数=100:5公鸡+3母鸡+1/3小鸡=100 对应 5i+3j+k/3 == 100
    • 总鸡数=00:公鸡+母鸡+小鸡=100 对应 i+j+k == 100
    • 小鸡必须为整数:小鸡%3=0 对应 k%3 == 0
#include<iostream>
using namespace std;
int main()
{
	int count = 0;
	for(int i = 1 ; i <= 100 ; i++)
	{
		for(int j = 1 ; j <= 100 ; j++)
		{
			for(int k = 1 ; k <= 100 ; k++)
			{
				count++;
				if(k%3 == 0 && 5*i+3*j+k/3 == 100 && i+j+k == 100){
					cout<<"鸡翁"<<i<<"只,鸡母"<<j<<"只,鸡雏"<<k<<"%d只"<<endl;
				}
			}
		}
	}
	cout<<"循环次数="<<count<<endl;
	return 0;
}

看得出来总循环次数是1000000次

3.第一次优化:缩小枚举范围

  • 因为一百块钱总共可以买20只公鸡,且母鸡和小鸡最少一只,因此公鸡的取值范围可以缩小为1-18也就是1≤i≤18
  • 因为一百块钱最多可以买34只母鸡(33.33),且公鸡和小鸡最少一只,因此母鸡的取值范围为1≤j≤32
  • 因为小鸡一元三只,所以这里无所缩小,公鸡和母鸡最少一只,因此小鸡的取值范围为1-98,也就是1≤k≤98
#include<iostream>
using namespace std;
int main()
{
	int count = 0;
	for(int i = 1 ; i <= 18 ; i++)
	{
		for(int j = 1 ; j <= 32 ; j++)
		{
			for(int k =1 ; k <= 98 ; k++ )
			{
				count++;
				if(k%3 == 0 && 5*i+3*j+k/3 == 100 && i+j+k==100){
					cout<<"鸡翁"<<i<<"只,鸡母"<<j<<"只,鸡雏"<<k<<"只"<<endl;
				}
			}
		}
	}
	cout<<"循环次数="<<count<<endl;
	return 0;
}

看得出来总循环次数是56448次

4.第二次优化:减少枚举变量

  • 因为公鸡,母鸡和小鸡的总数是100,所当公鸡和母鸡确定的时候,小鸡就可以用总数减去公鸡,减去母鸡来表示也就是k=100-i-j;
#include<iostream>
using namespace std;
int main()
{
	int count = 0;
	for(int i = 1 ; i <= 18 ; i++)
	{
		for(int j = 1 ; j <= 32 ; j++)
		{
			count++;
			int k = 100 - i - j;
			if(k%3 == 0 && 5*i+3*j+k/3 == 100){
				cout<<"鸡翁"<<i<<"只,鸡母"<<j<<"只,鸡雏"<<k<<"只"<<endl;
			}
		}
	}
	cout<<"循环次数="<<count<<endl;
	return 0;
}

看得出来总循环的次数是576

5.第三次优化:进一步减少枚举变量

  • 先来看三个枚举变量之间的关系
    • i+j+k=100
    • 5i+3j+k/3=100
      利用上述二式,消去k得14i+8j=200–>7i+4j=100
      j = (100-7i)/4
      k = 100 - (100-7i)/4
  • 从7i+4j=100可以推出j最小取1,则4j为4,7i最大为96,故i的取值范围为1-13
#include<iostream>
using namespace std;
int main()
{
	int count = 0;
	for(int i = 1 ; i <= 13 ; i++)
	{
		count++;
		int j = (100-7*i)/4;
		int k = 100 - j -i;
		if( (100-7*i)%4 == 0  && k%3 == 0){
			cout<<"鸡翁"<<i<<"只,鸡母"<<j<<"只,鸡雏"<<k<<"只"<<endl;
		}
	}
	cout<<"循环次数="<<count<<endl;
	return 0;
}

看得出来总循环次数减少到了13
大家可以看得出来枚举法的总体思路是比较简单的并不复杂,所以我们需要尽可能的去优化它。从最开始的1000000优化到最后的13次,可以看出优化的作用,更可以从中体会到算法的魅力!

4个cpp源文件下载:点击下载
其实没必要下载,自己从代码框中复制就可以了

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值