回溯算法

引言

寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。理论上,当候选解数量有限并且通过检查所有或部分候选解能够得到所需解时,上述方法是可行的。
不过,在实际应用中,很少使用这种方法,因为候选解的数量通常都非常大(比如指数级,甚至是大数阶乘),即便采用最快的计算机也只能解决规模很小的问题。
对候选解进行系统检查的方法有多种,其中回溯和分枝定界法是比较常用的两种方法。按照这两种方法对候选解进行系统检查通常会使问题的求解时间大大减少(无论对于最坏情形还是对于一般情形)。事实上,这些方法可以使我们避免对很大的候选解集合进行检查,同时能够保证算法运行结束时可以找到所需要的解。因此,这些方法通常能够用来求解规模很大的问题。

概念

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法(一种选优搜索法,按选优条件向前搜索,以达到目标)。当搜索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术称为:回溯法,而满足回溯条件的某个状态的点称为:“回溯点”。
回溯法实际是穷举算法,按问题某种变化趋势穷举下去,如某状态的变化用完还没有得到最优解,则返回上一种状态继续穷举。
许多复杂的,规模较大的问题都可以使用回溯法,回溯算法有“通用解题方法”的美称,其采用了一种“走不通就掉头”思想作为其控制结构,用它可以求出问题的所有解和任意解。
它的应用很广泛,很多算法都用到回溯法,例如,迷宫,八皇后问题,图的m着色总是等都用到回溯法,当然其中还使用了其他策略。

最大值段和(分治法,动态规划)

问题

概念:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整均为负数时定义子段和为0,依此定义,所求的最优值为:Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n
一个数组a[]:需要求最大子段和的数组;
一个数组b[]:数组a子段和的数组,{a[0],a[0]+a[1],a[0]+a[1]+a[2]...........}
例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。

解题

分治法

思路

如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和:
a[]:1..........................n
分段处理:1..........n/2........n

三种情况

  • a[1:n]的最大子段和与a[1:n/2]的最大子段和相同(左边的子段和)
  • a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同(右边的子段和)
  • a[1:n]的最大子段和为a[i]+…+a[j],并且1<=i<=n/2,n/2+1<=j<=n。(子段和=左边子段和+右边子段和)

对于(1)和(2)两种情况可递归求得,但是对于情况(3),容易看出a[n/2],a[n/2+1]在最大子段中。
第3种情况:我们可以在a[1:n/2]中计算出s1=max(a[n/2]+a[n/2-1]+…+a[i]),0<=i<=n/2,并在a[n/2+1:n]中计算出s2= max(a[n/2+1]+a[n/2+2]+…+a[i]),n/2+1<=i<=n。则s1+s2为出现情况(3)的最大子段和。

分治算法

基本思想

当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。
即一种分目标完成程序算法,简单问题可用二分法完成。
Java有ForkJoin模式,MongoDB有MapReduce模式,这些都是分而治之的思想。

步骤

分治法解题的一般步骤:

  1. 分解,将要解决的问题划分成若干规模较小的同类问题。
  2. 求解,当子问题划分得足够小时,用较简单的方法解决。
  3. 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。

(转载)01背包问题(动态规划算法)

概述

有n个物品,第i个物品价值为v,重量为w,其中v和w均为非负数,背包的容量是W。现需要考虑如何选择装入背包的物品,使装入背包的物品总价值最大。

物品编号 1 2 3 4 5
价值v 4 5 10 11 13
重量w 3 4 7 8 9


动态规划算法

引言

在现实生活中,有一类活动的过程,由于它的特殊性,可将过程分成若干个互相联系的阶段,在它的每一阶段都需要作出决策,从而使整个过程达到最好的活动效果。当然,各个阶段决策的选取不是任意确定的,它依赖于当前面临的状态,又影响以后的发展,当各个阶段决策确定后,就组成一个决策序列,因而也就确定了整个过程的一条活动路线。
这种把一个问题看作是一个前后关联具有链状结构的多阶段过程就称为多阶段决策过程,这种问题就称为多阶段决策问题。
多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化问题的方法为动态规划方法。

概念

动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。
动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。不像搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。
因此在学习时,除了要对基本概念和方法正确理解外,必须具体问题具体分析处理,以丰富的想象力去建立模型,用创造性的技巧去求解。我们也可以通过对若干有代表性的问题的动态规划算法进行分析、讨论,逐渐学会并掌握这一设计方法。

多阶段决策问题

如果一类活动过程可以分为若干个互相联系的阶段,在每一个阶段都需作出决策(采取措施),一个阶段的决策确定以后,常常影响到下一个阶段的决策,从而就完全确定了一个过程的活动路线,则称它为多阶段决策问题。
各个阶段的决策构成一个决策序列,称为一个策略。每一个阶段都有若干个决策可供选择,因而就有许多策略供我们选取,对应于一个策略可以确定活动的效果,这个效果可以用数量来确定。策略不同,效果也不同,多阶段决策问题,就是要在可以选择的那些策略中间,选取一个最优策略,使在预定的标准下达到最好的效果。

变位词(编程珠玑)

问题

给定一本英语单词词典,请找出所有的变位词集。所谓的变位词是指,组成各个单词的字母完全相同,只是字母排列的顺序不同。
例如,“pots”,”stop”和“tops”互为变位词,因为每个单词都可以通过改变其他单词中字母的顺序来得到。

解决思路

编程珠玑的变位词程序要按照三个步骤来执行,其中前一个步骤程序的输出作为下一个步骤程序的输入:

  • 程序标识单词。
  • 程序排序标识后的文件。
  • 程序将这些单词压缩为每个变位词类一行的形式。

单词的字典的处理过程:

由以上可看出需要三个程序的处理。

sign程序

假设输入单词的长度不超过100,对每个输入的单词依照字母进行排序,将结果输入这个单词所对应的“签名”。

sort程序

程序排序后的输出的“签名”,对其输出的结果排序,如上图。

squash程序

将同一个变位词类中的各个单词放到同一行中。

(转载)Boyer-Moore(字符串匹配)

引言

KMP它并不是效率最高的算法,实际采用并不多。各种文本编辑器的”查找”功能(Ctrl+F),大多采用Boyer-Moore算法。

Boyer-Moore算法不仅效率高,而且构思巧妙,容易理解。1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了这种算法。
在用于查找子字符串的算法当中,BM(Boyer-Moore)算法是目前被认为最高效的字符串搜索算法。 一般情况下,比KMP算法快3-5倍。该算法常用于文本编辑器中的搜索匹配功能,比如大家所熟知的GNU grep命令使用的就是该算法,这也是GNU grepBSD grep快的一个重要原因。

(转载)字符串匹配(KMP)

引言

简单匹配模式算法的效率不高,原因在于匹配过程中有回溯。
示例:从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位。

我们只需要比较i指针指向的字符和j指针指向的字符是否一致。如果一致就都向后移动,如果不一致,如下图:

A和E不相等,那就把i指针移回第1位(假设下标从0开始),j移动到模式串的第0位,然后又重新开始这个步骤:

思想

S[i]!=P[j]达到失配点,主串S要回到原来的i+1的位置(回溯),模式串P要回到第一个字符的位置,然后继续比较。每次到达失配点时,串S和串P的指针i,j都要回溯,因此效率比较低。

(转载)A星+(最优路径算法)

转帖:A*寻路算法介绍

介绍

你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?
如果是的话,请看这篇教程,我们会展示如何使用A寻路算法来实现它!
在网上已经有很多篇关于A
寻路算法的文章,但是大部分都是提供给已经解基本原理的高级开发者的。
本篇教程将从最基本的原理讲起。我们会一步步讲解A寻路算法,幷配有很多图解和例子。
不管你使用的是什么编程语言或者操作平台,你会发现本篇教程很有帮助,因为它在非编程语言的层面上解释算法的原理。稍后,会有一篇教程,展示如何在Cocos2D iPhone 游戏中实现A
算法。
现在找下到达一杯咖啡因饮料和美味的零食的最短路径,开始吧!

一只探路猫

让我们想象一下,有一款游戏,游戏中一只猫想要找到获取骨头的路线。
“为什么会有一只猫想要骨头?!”你可能会这么想。在本游戏中, 这是一只狡猾的猫,他想捡起骨头给狗,以防止被咬死!
现在想像一下下图中的猫想找到到达骨头的最短路径。

不幸的是,猫不能直接从它当前的位置走到骨头的位置,因为有面墙挡住去路,而且它在游戏中不是一只幽灵猫!
游戏中的猫同样懒惰,它总是想找到最短路径,这样当他回家看望它的女朋友时不会太累。
但是我们如何编写一个算法计算出猫要选择的那条路径呢?A*算法拯救我们!

简化搜索区域

寻路的第一步是简化成容易控制的搜索区域。
怎么处理要根据游戏来决定。例如,我们可以将搜索区域划分成像素点,但是这样的划分粒度对于我们这款基于方块的游戏来说太高(没必要)。
作为代替,我们使用方块(一个正方形)作为寻路算法的单元。其他的形状类型也是可能的(比如三角形或者六边形),但是正方形是最简单并且最适合我们需求的。
像那样去划分,我们的搜索区域可以简单的用一个地图大小的二维数组去表示。所以如果是25*25方块大小的地图,我们的搜索区域将会是一个有625个正方形的数组。如果我们把地图划分成像素点,搜索区域就是一个有640,000个正方形的数组(一个方块是32*32像素)!
现在让我们基于目前的区域,把区域划分成多个方块来代表搜索空间(在这个简单的例子中,7*6个方块 = 42 个方块)。

(转载)2048-AI算法分析

1
针对目前火爆的2048游戏,有人实现了一个AI程序,可以以较大概率(高于90%)赢得游戏,并且作者在stackoverflow上简要介绍了AI的算法框架和实现思路。但是这个回答主要集中在启发函数的选取上


针对目前火爆的2048游戏,有人实现了一个AI程序,可以以较大概率(高于90%)赢得游戏,并且作者在stackoverflow上简要介绍了AI的算法框架和实现思路。但是这个回答主要集中在启发函数的选取上,对AI用到的核心算法并没有仔细说明。这篇文章将主要分为两个部分,第一部分介绍其中用到的基础算法,即Minimax和Alpha-beta剪枝;第二部分分析作者具体的实现。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×