热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【智力题】过桥问题和倒水问题

原文:http:blog.csdn.netmorewindowsarticledetails7481851过桥问题和倒水问题都是笔试面试中的热门智力题,

原文:http://blog.csdn.net/morewindows/article/details/7481851

过桥问题和倒水问题都是笔试面试中的热门智力题,不但微软、GOOGLE、百度、腾讯等公司采用,甚至在IQ测试与公务员考试中都能见到。本文不但教你如何快速用手算来解决这两种问题,并且教你如何用程序代码来计算这两种问题。绝对让你大有收获。

一.过桥问题

在漆黑的夜里,四位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,四个人一共只带了一只手电筒,而桥窄得只够让两个人同时通过。如果各自单独过桥的话,四人所需要的时间分别是1,2,5,8分钟;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,你如何设计一个方案,让用的时间最少。

这个题目被微软、GOOGLE、百度、华硕、建设银行等很多公司用作笔试题或面试题。当然也有用在IQ测试中。

解答其实也容易,能者多劳这四个字就足以形容解答方案了——用时短的人必须要多跑几趟以便传递手电筒。

设这四个人叫做A,B,C,D,他们所需要的时间分别是1,2,5,8分钟。

第一步:AB过桥,花费2分钟。

第二步:A回来,花费1分钟。

第三步:CD过桥,花费8分钟。

第四步:B回来,花费2分钟。

第五步:AB过桥,花费2分钟。

这样只要花费2+1+8+2+2=15分钟,下面再来考虑如何用程序来解决这类问题,在写程序之前还有个细节要考虑下,比如A,B,C,D四个人所需要的时间分别是1,8,9,10分钟。

方案一

第一步:AB过桥,花费8分钟。

第二步:A回来,花费1分钟。

第三步:CD过桥,花费10分钟。

第四步:B回来,花费8分钟。

第五步:AB过桥,花费8分钟。

一共要8+1+10+8+8=35分钟。

方案二

第一步:AB过桥,花费8分钟。

第二步:A回来,花费1分钟。

第三步:AC过桥,花费9分钟。

第四步:A回来,花费1分钟。

第五步:AD过桥,花费10分钟。

一共要8+1+9+1+10=29分钟。

因此可以得出更加细化的解决方案——要么是最快者将最慢的2个送过桥,要么是最快的2个将最慢的2个送过桥。即将过桥的人按其过桥的时间从小到大排列,设为A,B,…… Y,Z。其中AB是最快的二个,YZ是最慢的二个。那么就有二种方案:

方案一 最快者将最慢的2个送过桥

第一步:AZ过桥,花费Z分钟。

第二步:A回来,花费A分钟。

第三步:AY过桥,花费Y分钟。

第四步:A回来,花费A分钟。

这四步后总人数就减小2个,花费时间为A + A + Y + Z分钟。

方案二 最快的2个将最慢的2个送过桥

第一步:AB过桥,花费B分钟。

第二步:A回来,花费A分钟。

第三步:YZ过桥,花费Z分钟。

第四步:B回来,花费B分钟。

这四步后总人数同样减小2个,花费时间为A + B + B + Z分钟。

这样,每次比较一下这二种方案就能将总人数减小2。然后我们再考虑一些边界情况:

有三个人过桥设为A,B,C(已经排好序,下同)。应该花费A + B + C分钟。

有二个人过桥设为A,B。那么肯定是花费B分钟。

有一个人过桥设为A。肯定花费A分钟。

 

//热门智力题 - 过桥问题
#include
#include

const int MAXN = 1000;
int cmp(const void *x,const void *y)
{
return *(int *)x-*(int *)y;
}
int main()
{cout
<<"热门智力题 - 过桥问题"<<endl;cout<<" --by MoreWindows( http://blog.csdn.net/MoreWindows )--\n"<<endl; int n, i, sum, a[MAXN];cout<<"请输入人数&#xff1a;";cin>>n;cout<<"请输入每个人过桥时间&#xff0c;以空格分开"<<endl;for (i &#61; 0; i )cin>>a[i];qsort(a, n, sizeof(a[0]), cmp);sum &#61; 0;for (i &#61; n - 1; i > 2; i &#61; i - 2){ //最小者将最大2个送走或最小2个将最大2个送走if (a[0] &#43; a[1] &#43; a[1] &#43; a[i] 0] &#43; a[0] &#43; a[i - 1] &#43; a[i])sum &#61; sum &#43; a[0] &#43; a[1] &#43; a[1] &#43; a[i];elsesum &#61; sum &#43; a[0] &#43; a[0] &#43; a[i - 1] &#43; a[i]; }if (i &#61;&#61; 2)sum &#61; sum &#43; a[0] &#43; a[1] &#43; a[2];else if (i &#61;&#61; 1) sum &#61; sum &#43; a[1];else sum &#61; a[0];cout<<"最短过桥时间为&#xff1a;"<endl;return 0;
}

程序运行结果如下&#xff1a;

 

二&#xff0e;倒水问题

这个题目的版本非常之多&#xff0c;有微软版的&#xff0c;腾讯版的&#xff0c;新浪版的等等&#xff0c;最常见的是给你一个容量为5升的桶和一个容量为3升的桶&#xff0c;水不限使用&#xff0c;要求精确得到4升水。

解法肯定有很多&#xff0c;可以用宽度优先搜索&#xff08;BFS&#xff09;&#xff0c;也可以用穷举法。穷举法实现比较方便&#xff0c;其基本思想是用&#xff1a;用小桶容量的倍数对大桶的容量进行取余。比如3升的桶和5升的桶得到4升水可以这样做&#xff1a;

3 % 5 &#61; 3

6 % 5 &#61; 1

9 % 5 &#61; 4

成功得到4升水。&#xff08;PS&#xff1a;上面的过程用如何用文字描述了&#xff1f;&#xff09;

同样&#xff0c;用7升的桶和11升的桶得到2升水可以这样做&#xff1a;

7 % 11 &#61; 7

14 % 11 &#61; 3

21 % 11 &#61; 10

28 % 11 &#61; 6

35 % 11 &#61; 2

成功得到2升水。

哈哈&#xff0c;有了这个基本思想在用笔算答案时简直是遇神杀神&#xff0c;遇佛杀佛&#xff0c;又方便又快速&#xff01;如果要求用程序来实现如何做了&#xff1f;easy&#xff0c;将倒水问题的基本思想用易于编程的话来翻译下——不断用小桶装水倒入大桶&#xff0c;大桶满了立即清空&#xff0c;每次判断下二个桶中水的容量是否等于指定容量。有了这个倒水问题的编程指导方针后代码非常容易写出&#xff1a;

 

//热门智力题 - 打水问题
//基本思想&#xff1a;用小桶容量的倍数对大桶的容量进行取余。
//指导方针&#xff1a;不断用小桶装水倒入大桶&#xff0c;大桶满了立即清空&#xff0c;
//每次判断下二个桶中水的容量是否等于指定容量。
#include
#include

#include
<string>
using namespace std;
const string OPERATOR_NAME[7] &#61; {"装满A桶","装满B桶","将A桶清空","将B桶清空","A桶中水倒入B桶","B桶中水倒入A桶","成功"
};
int main()
{cout
<<"热门智力题 - 打水问题"<<endl;cout<<" --by MoreWindows( http://blog.csdn.net/MoreWindows )--\n"<<endl;int a_volume, b_volume, goal_volume;vector<string> record; //记录操作步数int ai;int i, a_water, b_water;cout<<"请输入A桶容量&#xff0c;B桶容量&#xff0c;目标容量&#xff1a;";cin>>a_volume>>b_volume>>goal_volume;a_water &#61; b_water &#61; 0; //A桶&#xff0c;B桶中有多少升水char szTemp[30];while (true){if (a_water &#61;&#61; 0)//A桶没水,就装满水
{a_water &#61; a_volume;sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[0] &#43; szTemp);//fill A
}else{//如果A桶的水比(B桶容量-B桶的水)要多if (a_water > b_volume - b_water){//A桶的水&#61;&#61;A桶的水&#43;B桶的水-B桶容量a_water &#61; a_water &#43; b_water- b_volume;b_water &#61; b_volume; //B桶的水装满了sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[4] &#43; szTemp);//A->B if (a_water &#61;&#61; goal_volume)break;b_water &#61; 0; //将B桶清空sprintf(szTemp, " A:%d B:%d", a_water, b_water); record.push_back(OPERATOR_NAME[3] &#43; szTemp);}else{//B桶的水&#61;&#61;A桶的水&#43;B桶的水b_water &#43;&#61; a_water; a_water &#61; 0;sprintf(szTemp, " A:%d B:%d", a_water, b_water);record.push_back(OPERATOR_NAME[4] &#43; szTemp);//A->Bif (b_water &#61;&#61; goal_volume) break;}}}record.push_back(OPERATOR_NAME[6]); //successcout<<"\n---------------------------------------------------"<<endl;cout<<"一个可行的倒水方案如下"<<endl;vector<string>::iterator pos;for (pos &#61; record.begin(); pos !&#61; record.end(); pos&#43;&#43;)cout<<*pos<<endl;cout<<"---------------------------------------------------"<<endl;return 0;
}

程序运行结果如下&#xff1a;

 

注意这里只是给出一个可行的倒水方案&#xff0c;不一定是最优解。另外倒水问题要注意下像2升的桶和4升的桶得到3升水这种不可解的情况&#xff0c;这种不可解情况在用本文中对倒水问题所总结的基本思想计算时会得到循环数列。其根本原因是二个桶容量的最大公约数无法被目标容量所整除&#xff0c;如6升的桶和9升的桶无法得到2升水是因为69的最大公约数是3GCD(6&#xff0c;9)&#61;33无法整除2

倒水问题也也容易推广到多个桶的情况&#xff0c;分析方法和上文差不多&#xff0c;这里就不再赘述了。

 

过桥问题和倒水问题就讲解到此&#xff0c;相信以后这二类问题都不会再困扰大家了^_^。

 

 

转:https://www.cnblogs.com/theCambrian/p/3474785.html



推荐阅读
  • C/C++利用栈和队列实现停车场管理系统【C++教程】
    数据结构的课程设计一般都不是很好理解,今天小编为大家总结了一下c和c++版本的常见栈和队列的的停车场管理程序,需要 ... [详细]
  • [Offer收割]编程竞赛第8轮 A 小Ho的完美主义倾向
    题目链接:小Ho的完美主义倾向题目描述:小Ho在一条直线型的街道上漫步。这条街道由若干块长度为L的石板铺设而成,因此每隔L的距离就会出现一道石板间的接缝。小Ho对这些规律排列的接缝产生了浓厚的兴趣,他决定研究如何在这条街道上行走,以满足自己对完美路径的追求。本题要求在给定的约束条件下,计算出小Ho能够实现其目标的所有可能方案数。 ... [详细]
  • CatchThatCowTimeLimit:50002000MS(JavaOthers)MemoryLimit:3276832768K(JavaOt ... [详细]
  • 题目1:给定一个非空数组A,包含有N个整数,起始下标为0。数组包含有奇数个元素,其中除了唯一一个元素之外,其他 ... [详细]
  • 7.2 利用关系运算符与表达式进行数值对比分析
    在C语言中,关系运算符和表达式是进行数值对比分析的基础工具。本节详细介绍了真值的概念及其在编程中的应用,包括布尔类型(_Bool)的引入,以及关系运算符的优先级。通过具体示例,展示了如何在 `while` 循环中使用关系表达式来控制程序流程。这些内容对于理解和编写高效的条件判断逻辑至关重要。 ... [详细]
  • PAT甲级 1068 寻找更多硬币 (30分) 01背包问题与路径优化
    PAT甲级 1068 寻找更多硬币 (30分) 01背包问题与路径优化 ... [详细]
  • 基于灰度直方图的水果识别系统开发:MATLAB源代码及图形用户界面设计
    基于灰度直方图的水果识别系统开发:MATLAB源代码及图形用户界面设计 ... [详细]
  • 金字塔图表:自定义可视化与模拟漏斗分析
    金子塔图,自定义图表,伪漏斗图简易的金字塔图,设置不太灵活,可供使用者参考,需要使用者根据页面的需求复杂度等再做修改。另附链接地址:https:www.isqqw.compcent ... [详细]
  • 本章深入探讨了Java中的多态特性,这是面向对象编程的核心概念之一。多态指的是同一操作作用于不同的对象时,可以有不同的解释和执行方式。在Java中,多态通过父类引用变量引用子类对象来实现,即 `父类类型 引用变量名 = new 子类类型();`。这种方式允许程序在运行时根据实际对象的类型动态地选择合适的方法执行,从而提高代码的灵活性和可扩展性。此外,本章还详细介绍了多态的应用场景和注意事项,帮助读者更好地理解和运用这一重要概念。 ... [详细]
  • 算术表达式分析与解析技术初探
    本文初步探讨了算术表达式的分析与解析技术,针对作者在职业转型过程中发现自身算法基础薄弱的问题,决定在接下来的三个月内,系统地学习和掌握常用数据结构与算法,以提升个人技术能力。研究内容不仅涵盖了基本的算术表达式解析方法,还深入讨论了其在实际应用中的优化策略,为相关领域的进一步研究奠定了基础。 ... [详细]
  • AngularJS uirouter模块下的状态管理机制深入解析
    本文深入探讨了 AngularJS 中 ui-router 模块的状态管理机制。通过详细分析状态配置、状态转换和嵌套状态等核心概念,结合实际案例,帮助开发者更好地理解和应用这一强大工具,提升单页面应用的开发效率和用户体验。 ... [详细]
  • 本文介绍了一个基于C++标准库实现的INI文件读写操作类。该类在现有网络资源的基础上进行了扩展和优化,增加了获取当前可执行文件路径和宽字节与多字节字符串转换的功能。通过这些增强功能,该类能够更好地适应各种应用场景,提高代码的可移植性和健壮性。具体实现细节请参见 `IniFileSTL.h` 文件。 ... [详细]
  • 探索Golang中实现MD5加密的两种高效技术
    本文探讨了在Golang中实现MD5加密的两种高效方法。通过详细分析标准库 `crypto/md5` 的使用技巧和第三方库的性能优势,提供了丰富的代码示例和性能对比数据,帮助开发者选择最适合其应用场景的实现方式。此外,文章还讨论了MD5算法的安全性问题及其在现代应用中的局限性,为读者提供了全面的技术参考。 ... [详细]
  • 图像拼接技术深入解析:基于OpenCV 3.4的Stitching模块源码分析(下篇)
    本文继续深入探讨图像拼接技术,特别是在OpenCV 3.4的Stitching模块中的源码实现。通过与VLFeat的SIFT实现进行对比,详细分析了OpenCV在图像特征提取、匹配及拼接过程中的关键算法和技术细节,为读者提供了全面的技术解析和实践指导。 ... [详细]
  • c#学Java–Java基本语法1.类比JAVA .NETJVM CLRJDK  FCL2.java命名约定类名称应以大写字母开头,并成为容易理解的名词或组合。如 ... [详细]
author-avatar
谷智精源
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有