摘要: 数码的可达问题——8数码的推广 一个经典的问题:8数码 有一个3*3的九宫格,每格填有一个数0到8的数,互不相同。 填的数为0的格子可以和相邻的格子交换数。 给定九宫格的两种状态a,b,问能否通过一组交换使得a状态变成b状态。这个问题的标准解法是:把两个状态中的数(除0外)线性地排列出来并且分别求其逆序对数,若两个逆序对数的奇偶性相同,那么a,b相互可达。这个做法相当优美,但是它只是利用了这类问题的某个性质,究竟是什么性质呢?首先考虑一个2*2的棋盘容易发现,交换操作过后,只可能是当前状态的某个轮换。以此为基础,可以用数学归纳法得到一个结论:在任一 N*M的格子中,取任意三个非0的数,可以有. 阅读全文
posted @ 2012-02-28 11:56 zhouyichi 阅读(502) 评论(0) 推荐(0) 编辑
摘要: 在看下面这篇文章之前,先介绍几个理论知识,有助于理解A*算法。启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。估价函数:从当前节点移动到目标节点的预估费用;这个估计就是启发式的。在寻路问题和迷宫问题中,我们通常用曼哈顿(manhattan)估价函数(下文有介绍)预估费用。A*算法与BFS:可以这样说,BFS是A*算法的一个特例。对于一个BFS算法,从当前节点扩展出来的每一个节点(如果没有被访问过的话)都要放 阅读全文
posted @ 2012-02-01 22:31 zhouyichi 阅读(317) 评论(0) 推荐(0) 编辑
摘要: 概念:动态规划与很多算法一样,其初始思想是很简单的:把程序运行过程中已经算出来的,而且以后可以用到的信息记录下来,以后再用的时候只需要查表即可。我最开始见到的动态规划的最简单例子是求斐波那契数列:递归:Int f(int i){ If(i==0||i==1)return 1; Return f(i-1)+f(i-2);}动态规划:Int f[];f[0]=1;f[1]=1;For(int i=2;i<?;i++) F[i]=f[i-1]+f[i-2];容易看出来动态规划复杂度是线性的,递归的复杂度是指数级的//当然求解该数列还有一些//基于奇奇怪怪的数学结论的奇奇怪怪但是很高效的算法,不 阅读全文
posted @ 2012-01-30 19:21 zhouyichi 阅读(366) 评论(1) 推荐(0) 编辑
摘要: 复习感想——数据结构篇其四_trie及其变形//从一次失败的尝试谈起Trie树是用来处理多个字符串的数据结构。Trie树的初始动机很简单,利用字符串间的公共前缀来节约字符串存储的空间及加快检索的速度。 例如:单词 computer和command在trie树中只需要存储 com 和 puter及mand三个部分Trie树中从根节点出发到树上任意节点的路径都可以代表一个单词。Trie树很直观,其插入删除查找操作也很简单,这里不再赘述。下面着重看一个问题,我曾经对这个问题做过一个很失败的尝试,但是通过对trie的改进版能得到这个问题的很漂亮的解。例一:病毒二进制病毒审查委员会最近发现了如下规律:某 阅读全文
posted @ 2012-01-25 11:17 zhouyichi 阅读(429) 评论(0) 推荐(0) 编辑
摘要: 两道好玩的问题及我对“贪心思想”看法贪心是一种思想,所以我感觉给它下严格的定义不太合理。//要细致地研究它严格的定//义当然是必不可少的在最优化问题中,贪心思想指每次决策都选择当前最优解,而不用考虑全局的情况。贪心法是一种很高效的算法,但是容易知道贪心算法不一定正确,即从局部最优解不一定能够构造出全局最优解。所以说,贪心的难点之一便是 贪心 正确性的证明。总结出什么样的问题是能够用贪心法解决 是一件很困难的事情,不过大神们也弄出了一套名为“矩阵胚”的理论,矩阵胚用于贪心正确性的证明,但是貌似这套理论并没有涵盖所有的贪心问题(当然涵盖了相当大一部分),且太过于抽象(我看一点简单的部分都很吃力)。 阅读全文
posted @ 2012-01-24 15:08 zhouyichi 阅读(904) 评论(0) 推荐(0) 编辑
摘要: 线段树与树状数组线段树:顾名思义,线段树这个数据结构是为了表示“线段”来设计的(更准确的说法是“区间”),主要应用的是二分的想法。 //二分是divide and conquer 的一种,好的分治策略在降低复杂度方面往往有意想//到的效果//用二分思想设解决的很基础且很优美的问题有 LCA和RMQ 问题//额,知识有限且一时想不起来了,欢迎补充严格的定义很麻烦,但是用图来示例的话很容易理解,下图是表示[0,10]区间的线段树。图一线段树是一颗二叉搜索树,所以理所应当的,它支持以下操作:1.插入2. 删除3. 访问线段树的优势在于 快 , 而且在空间上的冗余不大(约两倍)例如:若要访问区间[1, 阅读全文
posted @ 2012-01-23 20:27 zhouyichi 阅读(380) 评论(0) 推荐(0) 编辑
摘要: 国家集训队1999论文集 陈宏:《数据结构的选择与算法效率——从IOI98试题PICTURE谈起》来煜坤:《把握本质,灵活运用——动态规划的深入探讨》齐鑫:《搜索方法中的剪枝优化》邵铮:《数学模型的建立、比较和应用》石润婷:《隐蔽化、多维化、开放化——论当今信息学竞赛中数学建模的灵活性》杨帆:《准确性、全面性、美观性——测试数据设计中的三要素》周咏基:《论随机化算法的原理与设计》国家集训队2000论文集 陈彧:《信息学竞赛中的思维方法》方奇:《动态规划》高寒蕊:《递推关系的建立及在信息学竞赛中的应用》郭一:《数学模型及其在信息学竞赛中的应用》江鹏:《探索构造法解题模式》李刚:《动态规划的深入讨 阅读全文
posted @ 2012-01-23 16:05 zhouyichi 阅读(343) 评论(1) 推荐(0) 编辑
摘要: Hash哈希表(hash table)的思路是根据关键码值直接访问。哈希表的思路很简单——根据关键码值直接计算出信息的存储地址。通常会为hash table 分配一个一维数组的存储空间,二维数组或多维数组用得比较少但是多维数组应用到hash table上面有一些好处:在多关键字的情况下 hash函数的设计 显得自然设hash 函数是 h(K)Hash表一般支持以下几个操作。1. 插入:计算h(K)并插入2. 查找:计算h(K)并访问3. 删除:增加一些删除标记,以后统一删除(较少使用)Hash的使用有两个比较需要注意的地方:1. Hash函数的设计2. 冲突的解决方法常用的hash函数:直接取 阅读全文
posted @ 2012-01-23 16:04 zhouyichi 阅读(236) 评论(0) 推荐(0) 编辑
摘要: 首先给出正常的并查集的几种操作的伪代码(普遍情况下的并查集)Define TYPE//TYPE 表示数据类型,相当于int之类的Meke_set(x) x.p=xFind_set(x)//路径压缩 TYPE y=x While y.p!=y Y=y.p TYPE z=x While z.p!=z TYPE MID=z.p z.p=y z=MID return yUnion(x,y) TYPE z=Find_set(x) TYPE p=Find_set(y) p.y=z并查集的基本思想是 把对象元素划分为一个一个的集合,并对其进行统一操作并查集有几个特点:1. 每个集合均有一个代表元素,通过这个 阅读全文
posted @ 2012-01-23 13:47 zhouyichi 阅读(301) 评论(0) 推荐(0) 编辑