《algorithm puzzles》——谜题

时间:2023-01-07 18:02:50

这篇文章开始正式《algorithm puzzles》一书中的解谜之旅了!

狼羊菜过河:

谜题:一个人在河边,带着一匹狼、一只羊、一颗卷心菜。他需要用船将这三样东西运至对岸,然而,这艘船空间有限,只容得下他自己和另一样东西(狼、羊或卷心菜)。若他不在场看管的话,狼就会吃掉羊,羊就会吃掉卷心菜。此人如何才能把这三个“乘客”没有损失的送到对岸?

提示:看到这个谜题的谜面非常小,利用穷举解决是绰绰有余的。

解谜:首先搬运的一定是羊,将其搬运到对岸,将其放下,随后驾空船回来,这次带狼或者卷心菜都可以,将其带到对岸,放下狼或者卷心菜,然后将羊装上床,然后将其运回来,放下羊并装入卷心菜或狼,然后再回来把羊运到对岸。

手套选择:

在抽屉里有20只收到。其中,5双黑手套,3双棕色手套和2双灰色手套。你只能在黑暗中挑手套,并且只有将手套跳出之后才能检查其颜色。最少要挑几次才能满足以下条件?

(a)至少挑出一双颜色匹配的手套。

(b)所有颜色的手套都至少挑出一双匹配的。

提示:这里不仅要注意到题干所说最少,更关键的是意识到设问中的“至少”意味着什么。

解谜:设问中的“至少”体现出一个”算法最差情况分析“,对于(a),最坏的情况是拿到5只黑色左(右)手套、3只棕色左(右)手套、2只灰色左(右)手套,随后取任何一个手套,都必将得到一双同颜色的手套,因此至少需要拿11只。(这里默认手套分左右,而袜子不分左右,虽然现在的确有分左右的袜子……)。同理,对于(b),我们至少需要拿19只。

矩阵切割:

将一个矩形切成n(n>1)个直角三角形,有多少种方法?

提示:这里给出的谜面是不确定的,因此考虑解决问题的通法,考虑到构造直角三角形的方法,这里需要从递推的角度找到规律。

解谜:我们设置F[n]切割成n个直角三角形的方法数。当n是偶数,我们在F[n/2]的基础上,将每一个直角三角形一分为二,即F[n] = F[n/2];当n是奇数的时候,我们在F[n-1]的基础上,选择n-1个三角形中的任意一个,将其一分为二,即F[n] = (n-1)F[n-1]。而对于起始情况,有F[2] = 2.

士兵渡河:

25个士兵组成的小分队需要渡河,可是河宽且深,周围也看不到桥。他们发现河岸边有一个小船,两个12岁的男孩正在上面玩耍。船很小,仅能承载两个男孩或一个士兵的重量。士兵应怎样渡河?船从一个岸边到另一个岸边来回共计几次?

提示:模拟出正确可行的渡河方案是关键。

解谜:容易看到,第一次渡河是不可能让1个士兵驾船渡河的,因此考虑让2个男孩先渡河,然后将1个男孩留在对岸,另1个男孩驾船回来,然后一个士兵驾船过去,对岸的男孩再驾船回来,这回到了最开始的状态,但是士兵的数量少了1.那么很显然,对于25个士兵,我们需要100次。

数数的手指:

一个小女孩正在用左手手指数数,从1到1000.她从拇指算作1开始数起,然后食指为2,中指为3,无名指为4,小指为5.接下来调转方向,无名指算作6,如此反复。问如果她按照这种方式数下去,最后结束时停在哪根手指上?

提示:模拟出这个过程以期找到规律。

解谜:我们在纸上稍微多写几个数字,很容易发现落在拇指上的数字满足8n + 1,随后的三个数字是递减1的(当然除了1~5),因此当n = 125的时候,拇指上的数字是1001,所以1000这个数字出现在食指上。基于这个规律,也可以将这个谜题的谜面推广成一般形式。

硬币中的假币:

有8枚外观完全一致的硬币,其中的一枚是假币,并且知道假币要比真币轻一些,可以使用天平但不能使用砝码,问最少几次才能把假币辨别出来?

提示:对,3次一定会找到那个假币的,但是是最少的次数么?

解谜:我们任取6枚硬币,将其平分在天平的两侧,会出现如下两种情况。

1.平衡,则我们称剩余的两个硬币,得到假币。

2.不平衡,较轻的那三枚硬币中存在假币,我们任取其中的两枚平分在天平两侧,即可找到假币。

可以看到,整个过程只需要两次。

我们容易将这个谜题的谜面给一般化然后来思考问题,然后二分硬币堆来找到假币,但是这种通用的方法好像并不适合这个题目中的特殊谜面。

那么解决这种问题是否存在一个解决一般性谜面的方法呢?这里卖个关子,笔者会在以后的谜题中给出介绍。

假币堆问题:

有10堆10枚外观完全一致的硬币,其中有一堆全部是假币,其它各堆中的硬币都是真币。所有的真币重量都是10g,假币则重11克。你有一把示数可读的秤,可以称出任意数目硬币的实际质量。问最少称几次才能将全部都是假币的那堆硬币辨别出来?

提示:需要考虑如何充分利用秤显示实际质量的功能。另外这里称几次表示读几次数。

解谜:既然秤能够显示数目,为了充分利用这一功能,我们就不单单用它来定性的比较大小了,而应该将其用到定量的计算当中。我们从第i堆硬币中拿出i个硬币,假设均为真币,实际质量为(1 + 2 + 3…… + 10)*10 = 550,那么我们只需测出实际质量m = 550 + j,这个j便是假币堆了,因此只需要1次即可。这是一种“表示变更”的思想。

平铺多米诺问题:

能否用单位长度2x1的多米诺牌将8x8的方格阵铺满?里面不包含由两张2x1多米诺并行排列而成的2x2的正方形。

提示:直觉告诉我们是不能的,如何证明呢?

解谜:我们用一个二维数组map[i][j]来8x8个方格中第i行第j列的那个1x1小格子。

我们首先假设覆盖map[1][1]的是横置的多米诺牌。则map[2][1]是竖置的多米诺牌,则map[2][2]是横置的多米诺牌......容易看到规律,map[i][i]是横置的多米诺牌覆盖、map[i][i+1]是竖置多米诺覆盖,我们考虑map[7][7]、map[7][8]、map[8][8],容易看到,按照上面的规律,是无法铺满map[8][8]的,而如果用横置多米诺去铺map[7][8]、map[8][8],这显然又是与题设相矛盾的。类似的,我们可以分析map[1][1]被竖置多米诺覆盖的情况。

正方形的拆分:

将一个正方形拆分成n个小正方形,找出数字n的所有取值可能,并且将这种拆分方法归纳成算法。

提示:考虑从n的奇偶性来归纳算法。

解谜:首先考虑n是偶数的时候,n=2显然无解,而n = 4的解是十分明显的。对于n = 2k时的情况,我们首先将正方形划分成kxk的小方格,为了方便描述,我们用方阵来表示,则第一行和k列形成了k-1个正方形,而剩余的k^2 - k + 1个小正方形,恰好又构成了一个大正方形,因此对于所有n为偶数且n≠2,都是有划分方案的。

而n = 2k + 1的情况下,有n = 2k - 2 + 3,我们基于n = 2k - 2的划分方案,选择任意一个小正方形,将其分割成4份,便可以得到n = 2k + 1的划分方案。而这种模式适用于k≥3时,对于k<3,即n<6,即n = 3、5,我们需要单独考虑。而我们会发现,这两种情况是无解的。

页码计数:

一本书的页码从1开始计数。如果所有用于标记页码的十进制数总和为1578,那么这本书共有多少页?

提示:题目描述是摘抄《算法谜题》上的原话,但是这里感觉可能由于翻译问题导致问题描述有一些偏差。拿一个例子来说明题目想描述的意思,比如对于页码12,这里记录十进制总和的sum需要+2.

解谜:在充分理解题意的基础上,我们开始对页数n进行位数的讨论。

n是一位数,则sun = n。

n是两位数,则sum = 9 + 2(n-9)。

n是三位数,则sum = 189 + 3(n-99)

....

然后将sum = 1576带入这一系列等式中,求出有意义的n即可。

煎饼制作:

需要制作n≥1个煎饼,所用的煎锅一次只能同时煎两个煎饼。煎饼两面都需要烤,完成一面的煎炸需要1分钟,无论一次制作一个煎饼还是同时煎两个煎饼。煎饼两面都需要烤,完成一面的煎炸需要1分钟,无论一次制作一个煎饼还是一次同事只做两个煎饼,设计一个算法计算做这项工作的最短时间。

提示:这道题目需要充分利用题设给出的贪心策略,即是否能够尽可能每次都烤两个饼的一面。

解谜:我们从n的奇偶性来分析,当n是偶数的时候,很容易看到,我们能够使得每次在煎锅上的都有两个饼,正好能够烤完。

而当n是奇数的时候,正是这个问题充分利用贪心策略的关键所在,我们从比较简单的n = 3时入手分析,按照往常的思维我们可能会认为需要4次,即先煎好1、2号饼,然后单独烤3号饼。其实时间还可以更少,考虑到它有6个面,我们看一看能否仅仅用3次就完成,这样就保证了每次都烤两个面的最优策略。

仍然以n = 3为例,我们先烤1、2号的一个面,然后再烤2、3号的一个面,然后烤1、3剩余的两个面。这种方法可以推广到所有n取奇数的情况。

综合起来,当n = 1时,我们最少需要2分钟;其余情况,我们最少需要n分钟。

三个水壶:

有一个充满水的8品脱的水壶和两个空水壶(分别是5品脱和3品脱)。通过将水壶完全倒满水和将水壶的水倒空这两种方式,在其中的一个水壶中得到4品脱的水。

提示:在理解题意的基础上,这道题目利用穷举的思想去尝试,很快就能够得到方法。

解谜:我们记整数对(a,b,c)表示8品脱、5品脱、3品脱水壶中存水量,则其实状态为(8,0,0).

这得到4品脱水的方法可以是如下的步骤(方法并不唯一):

(8,0,0) -> (3,5,0) -> (3,2,3) -> (6,2,0) -> (6,0,2) -> (1,5,2) -> (1,4,3).

三色排列:

一个长方形的方格板,上面有3行n列的格子,有n个红色、n个白色和n个蓝色总共3n个筹码随机放在这些格子中,每个格子有且仅有一个筹码。现在需要重新调换这些筹码的位置,使得方格板上每一列都能有三种不同颜色的筹码。,唯一允许的操作是交换同一行筹码的位置,设计一个算法完成这项任务或者这名这样的算法并不存在。

提示:其实如果存在这种算法,你也应该先证明其合理性,而最好的方法就是给出一种可行的方案。

解谜:首先,我们容易看到,通过操作,存在一种方法,使得n列中每一列都有且仅有一个红色。而后我们遍历这n列,假设当前我们遍历到第i列,无非会出现如下的两种情况:

(i)该列三个颜色不同。那么符合要求,继续遍历。

(ii)该列有两个颜色同色,这里假设是1红2白。那么我们可以看到,必然存在第j列,是1红2蓝,则我们很容易证,第i列和第j列至少有一组白、蓝在一行当中,那么调换,第i列和第j列均符合要求,继续遍历。

棍子切割:

一根长度为100的棍子需要被结成100根长度为1的小短,如果一次可以同时切割多跟棍子,问最少需要切几次?设计一个算法,处理此类问题,即对长度为n的棍子,计算切割所需要的最少次数。

提示:关键要想清楚怎样的切割方法是最优的。

解谜:我们首先进行模糊化的思考,我们就简单的比较将100切成1、99和将100切成50、50两种方案,很容易看到后者方案是比较好的,因为我们为了达到最优,倾向于把我们一刀能砍尽可能多的点(假设这跟棍子上有99个100等分点)。那么我们能够猜想,在终点附近进行切割可能会是最好的方案,因为这样我们总是能够得到一系列长度相似的木棍,然后我们就可以将这些木棍并排起来然后锯开。顺着这层思路,100切成50、25、13、7、4、2、1,共计7次。

这其实就是程序设计当中非常重要的二分思想,有点类似于细胞分裂,我们切割棍子的最优策略就是将我们手头有的x根棍子一起来一刀,得到2x根棍子,而保证出现这样的切割方法就是在棍子的中点附近进行切割。为何更好理解我们将其与细胞分裂联系起来,刚开始的一根木棍相当于一个细胞,然后几个操作其实就是分裂,按照最优化的切割方法,对于长度为n的木棍,设最优策略为k次,则有2^k = n,即k = log2 n(这也是很多算法分析当中会出现log的原因,即它基于了二分思想)。考虑到n不一定刚好是2的整数次幂,我们接下来需要讨论向上还是向下取整的问题。

容易看到,向下取整切出的是2^ ⌊log2 n⌋ < n,所以这里应该向上取证。

即,对于长度为n的棍子,最小的切割次数是⌈log2 n⌉。

《algorithm puzzles》——谜题的更多相关文章

  1. 《algorithm puzzles》——概述

    这个专题我们开始对<algorithm puzzles>一书的学习,这本书是一本谜题集,包括一些数学与计算机起源性的古典命题和一些比较新颖的谜题,序章的几句话非常好,在这里做简单的摘录. ...

  2. A Problem-Solving FlowChart &vert;&vert; 如何解决编程问题

    This is from book Cracking the coding interview, Gayle Laakmann Mcdowell. The flowchart can be used ...

  3. What are the 10 algorithms one must know in order to solve most algorithm challenges&sol;puzzles&quest;

    QUESTION : What are the 10 algorithms one must know in order to solve most algorithm challenges/puzz ...

  4. &lbrack;Algorithm&rsqb; Warm-up puzzles

    闲下来后,需要讲最近涉及到的算法全部整理一下,有个indice,方便记忆宫殿的查找 MIT的算法课,地球上最好:https://ocw.mit.edu/courses/electrical-engin ...

  5. Java异常&lpar;三&rpar; 《Java Puzzles》中关于异常的几个谜题

    概要 本章介绍<Java Puzzles>中关于异常的几个谜题.这一章都是以代码为例,相比上一章看起来更有意思.内容包括:谜题1: 优柔寡断谜题2: 极端不可思议谜题3: 不受欢迎的宾客谜 ...

  6. UOJ260 【NOIP2016】玩具谜题

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  7. codeforces A&period; Puzzles 解题报告

    题目链接:http://codeforces.com/problemset/problem/337/A 题意:有n个学生,m块puzzles,选出n块puzzles,但是需要满足这n块puzzles里 ...

  8. codeforces 377A&period; Puzzles 水题

    A. Puzzles Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/33 ...

  9. 【 POJ - 1204 Word Puzzles】(Trie&plus;爆搜&vert;AC自动机)

    Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special ...

随机推荐

  1. Java EE之servlet处理表单提交的请求

    1.在源包下新建一个Servlet页,取名为LoginServlet: package weinidingServlet;                            //该Servlet所 ...

  2. Java调用批处理或可执行文件

    import java.io.BufferedReader; import java.io.InputStreamReader; public class Test { public static v ...

  3. 自定义分页标签,并使分页标签能获得url中的参数

    如题,要实现一个分页功能,其次,要让分页标签“智能一点”,在分页时能自动带上url后面的参数 <tag> <description>分页标签</description&g ...

  4. Unity学习入门

    文章说明,文本内容基于配置文件进行依赖注入 unity介绍:Unity是由微软的Patterns & Practices团队开发的一个轻量级.可扩展的依赖注入(Dependency Injec ...

  5. SQL Server复制表结构和表数据生成新表的语句

    参考:http://topic.csdn.net/t/20020621/09/820025.html SELECT   *   INTO   newTableName   FROM   oldTabl ...

  6. 详谈再论JAVA获取本机IP地址

    首先,你如果搜索“JAVA获取本机IP地址”,基本上搜到的资料全是无用的.比如这篇:http://www.cnblogs.com/zrui-xyu/p/5039551.html实际上的代码在复杂环境下 ...

  7. Mac OS 安装phpMyAdmin

    http://www.coolestguyplanettech.com/installing-phpmyadmin-on-mac-osx-10-7-lion/

  8. ccfZ字形扫描

    问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan).给定一个n×n的矩阵,Z字形扫描的过程如下图所示: 对于下面的4×4的矩阵, 1 5 3 9 3 7 5 ...

  9. SQLAlchemy使用说明之ORM

    对象关系映射(Object Relation Map, ORM)可以将一个类映射为关系模式(数据表). 使用ORM比直接书写SQL在安全性,可读性上都有很大优势. Working with Relat ...

  10. 13个 ASP&period;NET MVC 的扩展

    ASP.NET MVC设计的主要原则之一是可扩展性.处理管线(processing pipeline)上的所有(或大多数)东西都是可替换的.因此,如果您不喜欢ASP.NET MVC所使用的约定(或缺乏 ...