热门标签 | 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



推荐阅读
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文介绍如何使用 NSTimer 实现倒计时功能,详细讲解了初始化方法、参数配置以及具体实现步骤。通过示例代码展示如何创建和管理定时器,确保在指定时间间隔内执行特定任务。 ... [详细]
  • 本文介绍了在Windows环境下使用pydoc工具的方法,并详细解释了如何通过命令行和浏览器查看Python内置函数的文档。此外,还提供了关于raw_input和open函数的具体用法和功能说明。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 本文介绍了如何在C#中启动一个应用程序,并通过枚举窗口来获取其主窗口句柄。当使用Process类启动程序时,我们通常只能获得进程的句柄,而主窗口句柄可能为0。因此,我们需要使用API函数和回调机制来准确获取主窗口句柄。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
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社区 版权所有