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

手里拿着一把锤子,看什么都像钉子。我们这个年代最厉害的锤子就是算法。——William Poundstone.
  解题是一种实用技能,怎么说呢,有点像游泳吧。我们学习任何使用技能的办法就是模仿和实践。——George Polya.
  如果想使得上课不那么无聊,那么没有比加入带有创造力的主题更好的办法了,这些主题的特点就是带有娱乐、幽默、美感和惊喜。——Martin Gardner
  给人以最大享受的,不是知识,而是钻研;不是拥有,而是跋涉。——Carl Friedrich Gauss
  若是我不小心遗漏了一些多少有用或必要的内容,还请多多包涵,因为人人都会犯错,也不可能预知一切。——Fibonacci

首先我们对“算法谜题”这个概念稍作释义,每个算法问题都应该有所谓的“谜面”,它可以是具体的,也可以是一般的。举个例子来说,给出利用天平检测出含有1枚假币的8枚硬币,这里的“8”就是一个谜面,或者更加抽象的说,在解决算法问题中我们致力于给出一个正确且高效的function(),一个计算的过程、一个有功能的函数,而显然谜题本身应该具备相应的自变量x,而f(x)就是这个问题的解。

在解决算法谜题的时候,我们有一些通用的解题策略,比如穷举、回溯、分治、减治、变治、贪心、动态规划、递归等,这篇文章就是主要从思想层面来介绍这些解决算法问题的工具利器,以达到提升算法思维的目的。

穷举:

幻方:构造一个三阶幻方。(3*3的格子中填充数字1~9,是的每一行、每一列、两条对角线上的数字和都相等)。

很容易想到,我们对于这样一个3*3的方格,有且仅有9!种填充数字的方法,然后我们进行一一验证找到符合的方案即可,然而这个过程貌似太过机械化,计算量也太大。这其实体现了穷举算法的两个特点,其一是解集可知性,我们在这里能够一目了然的知道这个问题中能够出现的所有情况。其二便其庞大的计算量和低效率,这一点使得其在解决谜面范围不确定或者较大的时候,显得捉襟见肘。

然而有没有更好的方法呢?我们易证每行、每列以及对角线的和是15,由对称性的思维,我们能够看出5应该放在正中间。(1-9,2-8,3-7,4-6,可以满足两行两列和两个对角线)剩余的部分我们只需要枚举为数不多的情况,便可得到最终解。

可以看到,这种方法本质上还是一种穷举,但是是一种范围极小的穷举,由于其基于了一定程度的优化处理,这往往是利用穷举策略时的核心所在。

基于递推关系的减治法和增量法:

名流问题:在总人数为n的人群中的名流,就是指不认识任何人,所有其他人都认识的人。问题的任务是:仅仅通过向人们提出形如“你是否认识某某”的问题,来识别出名流。

问题本身很简单,将n个人放入一个名流的预选集合A,我们随机抽取一个人,记为甲,询问他是否认识剩余n-1个人中的一个,记为乙。如果甲认识乙,那么将甲从名流的预选集合中排除,反之,则排除乙。能够看到,通过这一步选择,名流预选集合A的规模缩小了1,那么反复操作,必然可以找到名流。

这个问题非常简单,但是反映出来的思路却很重要。对于一个全局的大问题,我们利用它与一个更小规模的问题的递推关系,来将问题规模缩小,这就是所谓的减治法。相应的,所谓的增量法,就是基于一个小规模问题的解,我们尝试利用它与更大规模问题解的递推关机,来讲问题规模扩大。本质上讲,他们都是基于一种建立递推关系的思想来减小或扩大问题规模的一种方法。

分而治之:

三格骨牌谜题:使用3格骨牌填充一个缺了一块的2^n * 2^棋盘,缺的一格可是放在任意处。

我们将这个3格骨牌放在棋盘的正中间,我们能够看到,填充2^n * 2^n大棋盘的问题,变成了填充4个2^n-1 * 2^n-1小棋盘的问题,对于小棋盘,我们采取相同的策略,不断将某一个小问题分解成若干个小问题。

这里其实可以看到,分治思想和上文中我们介绍的减治好像有相通的地方,都致力将问题子问题话或者说是建立递推关系。可以将减治看作分治的一个特殊情况,他们本质的区别在于,减治将原问题缩小规模后,形成了一个子问题,而分治则会有多个。

变而治之:

数字填充:

有n个不同的数字,还有n个一系列>、<连接的空格。设计以算法将这些数字填到空格之中并满足空格之间的不等式关系。

题目要求仅仅给出一种符合要求的填充方式,因此我们需要考虑所使用的算法一定确定能够生成满足不等关系的方案。那么这里我们将使用变而治之策略中的一种方法——表示变更,即将数据进行预处理。

我们首先将这n个数字从小到大排序,我们用一个a[]来表示,然后开始检索前n-1个空格,如果第i个空格后面是">",那么将a[]中最大的元素放入第i个空格当中,然后删除这个元素。这样做的好处是,通过将n个数字的升序排序,我们能够保证每一次填充都是符合不等关系的,否则,对于一堆散乱的数字,我们的选择项太多而又无法保证不等关系的成立。

最优馅饼切割法:

在一块矩形的馅饼上切n刀,最多能把馅饼切成多少块?规定只能平行于馅饼的边进行横切或者竖切。

我们首先设横切x刀,竖切y刀,首先有x+y=n。其次我们应该能够看到,横切x刀将在原来的基础上得到x+1块小馅饼,纵切y刀将在原来的基础上得到y+1倍块小馅饼。(这个过程很像《度量》一书中给出的关于矩形面积计算公式的由来),设f表示切n刀后得到的小馅饼数,则我们可以得到如下的函数关系。

f = (x+1)(y+1),结合x+y=n我们进行替换,n作为参量,而f我们将其改成与横切数x(因为代换后仅有一个变量x)的函数关系。

即整个问题能够等价转化成这样,f(x) = -x^2 + nx + (n+1),x∈[0,n]且x∈Z,求f(x)的最大值。建立的数学模型后这个问题就显得容易了很多。

这便是变治的另一个层面——数学归约,即将实际问题找到合适而好处理的数学模型,是我们研究的理论知识的一个用武之地,这种在解决实际问题当时是非常重要的一种思路。笔者在《数学建模》的专栏中将会介绍更多的数学建模的实例。

《algorithm puzzles》——概述的更多相关文章

  1. 『TCP/IP详解——卷一:协议』读书笔记——01

    从今日起开始认真研读TCP/IP详解这本经典制作,一是巩固我薄弱的计算机网络知识,二来提高我的假期的时间利用率.将心得与思考记录下来,防止白看-哦耶 2013-08-14 18:47:06 第一章 概 ...

  2. 『TCP/IP详解——卷一:协议』读书笔记——10

    2013-08-22 22:57:17 3.8 ifconfig命令 这个命令在Linux系统下可以通过下面的指令阅读说明文档: ifconfig 由于书中作者用的系统比较早的某Unix系统,所以我的 ...

  3. 【TCP/IP详解 卷一:协议】第二章:链路层

    2.1 引言 链路层的三个目的: (1)为IP模块发送和接收IP数据报. (2)为ARP模块发送ARP请求和接收ARP应答.地址解析协议:ARP. (3)为RARP模块发送RARP请求和接收RARP应 ...

  4. TCP/IP详解学习笔记- 概述

    TCP/IP详解学习笔记(1)-- 概述1.TCP/IP的分层结构      网络协议通常分不同层次进行开发,每一层分别负责不同的同信功能.TCP/IP通常被认为是一个四层协议系统.      如图所 ...

  5. TCP/IP详解 卷一(第一章 概述)

    很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但TCP/IP协议族允许它们相互进行通信. 1.分层 TCP/IP不是一个协议,而是一个协议族,通常它被认为是一个四层的协议系统,下面展 ...

  6. 《TCP/IP详解卷一:协议》 概述

    分层           TCP/IP协议族是一组不同层次上的多个协议的组合.TCP/IP通常被认为是一个四层次协议系统.   链路层(数据链路层或网络接口层):通常包括操作系统中的设备驱动程序和计算 ...

  7. 【TCP/IP详解 卷一:协议】TCP的小结

    前言:TCP学习的综述 在学习TCP/IP协议的大头:TCP协议 的过程中,遇到了很多机制和知识点,详解中更是用了足足8章的内容介绍它. TCP协议作为 应用层 和 网络层 中间的 传输层协议,既要为 ...

  8. 【TCP/IP详解 卷一:协议】第十一章 UDP 用户数据报协议

    11.1 引言 UDP 是一个简单的 面向数据报 的运输层协议:进程的每个 输出操作 都正好产生一个 UDP数据报,并且组装成一份待发送的IP数据报. 这与 TCP 不一样,它是 面向流字符 的协议, ...

  9. 【TCP/IP详解 卷一:协议】第六章:DHCP 和自动配置

    简介 为了使用 TCP/IP 协议族,每台主机or路由器都需要一定的配置信息: IP地址 子网掩码 广播地址 路由或转发表 DNS 协议配置方法: 手动 通过使用网络服务来获得 使用一些算法来自动确定 ...

  10. 【TCP/IP详解 卷一:协议】第一章概论 学习笔记

    第一章 概述 游览了一下,本章主要是简介OSI模型的低层(1-4层).介绍了TCP/IP协议族的相关知识. TCP/IP的分层 Application <--> TCP / UDP < ...

随机推荐

  1. C#日期转换类

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Te ...

  2. angularjs 遇到Error: [$injector:unpr] Unknown provider: tdpicnews-serviceProvider <- tdpicnews-service <- tdpic-controller 错误

    define(['modules/tdpic-module', 'services/news-service', 'utilities/cryto'], function (app) { 'use s ...

  3. 限制UITextField/UITextView的输入字数与中文输入之后的英文换行问题

    要限制一个UITextField/UITextView的输入字数,首先想到的应该是通过UITextFieldDelegate/UITextViewDelegate的代理方法来限制,那么如何来更好的限制 ...

  4. js 模板引擎 - 超级强大

    本来没想写这篇文章,但是网上误导大众的文章太多了,所以今天就抽出半小时时间谈一下我对前端模板引擎的感受吧. 前端模板引擎相信大家都再熟悉不过了,市面上非常多的号称最好.最快.最牛逼的,随便就能找到一大 ...

  5. C# Winform 双屏显示

    双屏显示1 // 利用WinForm中的Screen类,即可比较方便地实现多窗体分别在多个屏幕上显示. //•获取当前系统连接的屏幕数量: Screen.AllScreens.Count(); //• ...

  6. 用VS2005写一个 C 的类库和用 C#来调用的示例

    一.用VS2005写一个 C 的类库的步骤: (1).建立一个空的Visual C++项目 (2).这时候在项目中可以看见 三个空目录 选中 "源文件" 目录,然后点鼠标右键,在弹 ...

  7. PHP面向对象(OOP):__call()处理调用错误

    在程序开发中,如果在使用对象调用对象内部方法时候,调用的这个方法不存在那么程序就会出错,然后程序退出不能继续执行.那么可不可以在程序调用对象内部 不存在的方法时,提示我们调用的方法及使用的参数不存在, ...

  8. 再说CSS3渐变——线性渐变

    渐变背景一直以来在Web页面中都是一种常见的视觉元素.但一直以来,Web设计师都是通过图形软件设计这些渐变效果,然后以图片形式或者背景图片的形式运用到页面中.Web页面上实现的效果,仅从页面的视觉效果 ...

  9. [r]How To Use Git To Create A Key

    怎样生成公钥(via) 工作流程 安装设置 git 下载最新版本的git http://git-scm.com/downloads 当你安装完成git的时候,你需要简单的配置一下,打开终端: 用户名 ...

  10. mysql数据库管理备份运维常用命令

    登陆mysql: mysql -u root -p password 远程访问开启((%)表示任何主机连接,可以换固定IP来访问远程连接): GRANT ALL ON *.* TO root@'%' ...