C++ 算法设计:鸡兔同笼问题的多种求解方法

问题:

今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?编程求雉兔各几何。

解法1:人肉计算机
手工解方程,程序直接输出答案,这是最短的程序,没有之一。

#include <iostream>
using namespace std;
int main()
{
	cout << "chickens = 23" << endl;
	cout << "rabbits  = 12" << endl;
	return 0;
}

解法2:方程求解
当然,也可以让计算机解方程,省去手工计算的工作量。

#include <iostream>
using namespace std;
int main()
{
	int m = 35;
	int n = 94;
	/*
		 x +  y = m
		 2x + 4y = n
	 */
	int x = (4 * m - n) / 2;
	int y = m - x;
	cout << "chickens = " << x << endl;
	cout << "rabbits  = " << y << endl;
	return 0;
}

解法3:暴力搜索
再省点事,方程也不需要我们来变换,直接让计算机逐个答案试探,反正计算机计算速度快,只要我们少动脑筋就行。

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x <= 35; ++x)
	{
		for (int y = 0; y <= 35; ++y)
		{
			if (x + y == 35 && x * 2 + y * 4 == 94)
			{
				cout << "chickens = " << x << endl;
				cout << "rabbits  = " << y << endl;
				return 0;
			}
		}
	}
	cout << "unsolvable!" << endl;
	return 0;
}

解法4:启发式搜索
其实上面的程序中,y不用循环,因为 y=35-x,这样只需要 x 循环 36 次就能把答案找出来,速度比上面提高 36 倍。尽管计算机速度很快,我们还是尽可能减少不必要的搜索工作。

#include <iostream>
using namespace std;
int main()
{
	for (int x = 0; x <= 35; ++x)
	{
		int y = 35 - x;
		if (x * 2 + y * 4 == 94)
		{
			cout << "chickens = " << x << endl;
			cout << "rabbits  = " << y << endl;
			return 0;
		}
	}
	cout << "unsolvable!" << endl;
	return 0;
}

解法5:随机求解
如果你对求x,y没思路,可以分析一下它们的取值范围,然后在取值范围内随机取值,然后检验一下这组随机值是否为符合答案要求,如果符合的话,问题就搞定了。

别看不起随机求解,很多复杂算法都用到了这种技巧,用的好的话,能解决很多无法用公式求解的难题。正所谓乱拳打死师傅啊!

#include <iostream>
using namespace std;
int main()
{
	while (true)
	{
		int x = rand() % 36;
		int y = rand() % 36;
		if (x + y == 35 && 2 * x + 4 * y == 94)
		{
			cout << "chickens = " << x << endl;
			cout << "rabbits  = " << y << endl;
			return 0;
		}
	}
	return 0;
}

解法6:烧脑筋求解方法
我觉得不炫耀一下技巧,显得太 low 了,用递归方法给出一段代码,慢慢烧脑筋去吧!

#include <iostream>
using namespace std;
int chickens(int m, int n)
{
	return 4 * m <= n ? 0 : 1 + chickens(m - 1, n - 2);
}
int main()
{
	cout << "chickens = " << chickens(35, 94) << endl;
	cout << "rabbits  = " << 35 - chickens(35, 94) << endl;
	return 0;
}

还可以利用 lambda表达式进一步化简,但对于初学者,意义不大了,有兴趣自己搞一下。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

许野平

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

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

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

打赏作者

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

抵扣说明:

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

余额充值