我国古代著名趣题之一。
《孙子算经》中这样描述:“今有鸡兔同笼,上有三十五头,下有九十四足,问鸡兔各几何?”
先来正确解的完整代码:
#include <iostream>
int main()
{
int rabbit, head, foot;
std::cin >> head >> foot;
rabbit = (foot - head * 2) / 2;
if (rabbit * 4 + (head - rabbit) * 2 != foot)
return -1;
else
std::cout << "chook has:" << head - rabbit
<< "\t"
<< "rabbit has:" << rabbit;
return 0;
}
一般对于这种简单的问题,像博主这样的渣渣新手们通常想到的都是暴力破解:
双重循环便利所有可能组合,再进行判断筛选,代码如下:
for (int t(1); t <= head; ++t)
{
for (int j(1); j <= head; ++j)
{
if (j + t == head && 4 * t +2 * j == foot)
std:cout << .....;
}
}
简单暴力,不用想!就是这么任性!
虽然博主是刚刚入门的渣渣但本着为了世界和平(认真脸)也要提醒那些和博主一样的渣渣新手们,这种方法是非常不值得提倡的!不值得提倡!不值得提倡!
重要的事情说三遍 哈哈
且不说这样的代码会暴露自己的水平,复杂度N*N这个样子足以让你在数据量大的时候等的崩溃,搞不好还会溢出呢
其实稍加思考,聪明一点的渣渣会想出这样的代码:
for (int j(0); j <= head; ++j)
{
t = head - j;
if (j * 2 + t * 4 == foot)
std::cout << .....;
}
这个代码时间复杂度为N,相比上一个代码而言,速度不知道提高了多少!
看吧,动脑子的作用就是这么神奇,稍加思考复杂度就从N*N 缩小到N,在你的聪明才智下心爱的电脑少算这么多次呢
你以为算到这里就结束了吗?少年,你真的too young too simple!!!
当初博主就是拿着这样一个自以为聪明的代码去找大神表扬,然后,然后就被现场碾压了
如何让复杂度直接变为1?
你没有听错,就是1!
对于刚刚了解基础语法的新手,在学会for之后基本上稍微多一点的数据就都往循环上扯
让我们来换一种思路
把它当成数学题来算:两个未知量,两个方程,让我们来解方程
设未知量j(鸡),t(兔). 有j + t = head; 2j + 4t = foot; 解方程之后有 t = (foot - 2head) / 2;
这不就皆大欢喜,一次计算就得出了结果!
具体代码如下:
rabbit = (foot - head * 2) / 2;
// 我们定义rabbit为int型,所以在上一步计算中,当头脚数量不匹配时有可能出现数值截取现象
// 所以在之后的需要判断计算之后兔子和小鸡的脚数与输入的总脚数是否相等,如果不相等则无解,直接结束
if (rabbit * 4 + (head - rabbit) * 2 != foot)
return -1;
else
std::cout << "chook has:" << head - rabbit
<< "\t"
<< "rabbit has:" << rabbit;
通过这一道题,博主真的收获很多:
1、拿到问题不要直接就做,分析思考想明白之后再开始敲代码;
2、同一问题多和别人交流,说不定别人的方法会让你眼前一亮;
3、编程的时候不要只局限与语言的特性,要将问题实际化,多换几种思路,注重自己思考的过程并尽力将之实现在代码上(不会编程的时候我遇到这个问题大脑是如何思考的,如何得出答案的);
4、要学会考虑时间复杂度,尽可能让代码简单,高效;
4、多看到书、多编程、还是自己太太太太渣
*ps:欢迎各位大神不嫌弃渣进行指正批评,也欢迎各位比我还渣的同学提问,我们一起成长