Xavier's Blog

USACO Section 3.1 Humble Numbers

| Comments

最直接的想法是枚举每个数,看是否能用S中的元素将其分解,但1<=N<=100000,第N个数肯定会很大,这样做肯定超时,放弃。

后来想利用STL中的set来解决,枚举某一个数,如果属于set,将其与S中各元素相乘的数放入set,如此循环,直至找到第N个数,提交后还是超时。看来即便是set,毕竟存取的效率不是O(1),性能还是有影响。

突然想到,这题不是跟poj的Ugly Number挺像的嘛,是Ugly Number的加强版。具体思想是:对于S中的每个元素p[i],设置一个下标pIdx[i],pIdx[i]指向humble number数组。进行N次循环,每次找出最小的p[i] * humble[pIdx[i]],将该数加入humble数组,然后pIdx[minIdx]++。这样就能由小到大找出第N个humble number了。

PS:其实这种方法生成的humble number只能保证非降序,比如2×3和3×2就会生成相同的humble number,这种情况要排除。

USACO Section 2.4 Cow Tours

| Comments

一个图,有至少2个连通分量,用分别属于不同连通分量的点对将这两个连通分量连接,使其“直径”最小,问最小直径为多少。(直径的定义为连通分量中点对的最短路径中最长的路径)

我的思路是:

1、Floyd算出点对最短路径

2、深搜找出不同连通分量

3、枚举同一连通分量中的点对最短路径,最大的作为该连通分量的直径,顺便算出一点到连通分量中最远点的距离

4、枚举不同连通分量的任意点对a和b,找出以下的最大值

a所在连通分量的直径
b所在连通分量的直径
ab的距离 + a到本连通分量最远距离 + b到本连通分量最远距离

5、找出这些最大值中的最小值

USACO Section 2.3 Controlling Companies

| Comments

明明是一道难度不大的题,我却做了N天才做出来,惭愧惭愧!看到题的第一想法就是如果A控制了B,就把B所占有的股份传给A以及A的母公司,并且这样递归下去。可自己编程会发生股份重复计算的情况,解决方法是当将B的股份更新到A上时(通过母公司的关系找到A),如果之前A已经直接或间接控制了B,那么如果再加就算是重复计算了。但在判断A是否直接或间接控制B时,又要判断是否有环。

后来在网上找到了一种解法:当发现A控制B时,将B的股份传给A,如果发现增加股份之后,A中的股份[A][i] > 50 并且A还没有控制i,则将(A, i)加入队列。一直循环操作,直至队列为空为止。

官方的解题报告中,其实就是我一开始想的递归的方法,他在更新(A, B)时:

  1. 如果A已经控制B,退出

  2. 若没有,control[A][B] = 1

  3. 将B的股份传给A

  4. 枚举已控制了A的i,递归更新(i, B)

  5. 枚举A的股份[A][k],如果大于50,递归更新(A, k)

USACO Section 2.3 Cow Pedigrees

| Comments

一棵树,每个节点有0或2个孩子,共N个节点,高度为K,问可以组成多少种不同的结构?

假设,当前树的节点问n,高度为k,那么子树可分为3种情况:

  1. 左子树高度为k-1,右子树高度为1~k-2

  2. 右子树高度为k-1,左子树高度为1~k-2

  3. 左右子树均为k-1

并且,满足题目要求的树的节点与高度有这样的关系:2*k-1 <= n <= 2k-1,可是根据这个关系枚举左右子树的节点数

于是就可以用递归+DP的方法解出这道题了。

(在对n <= 2k-1进行转化时,自己居然写成了k >= log(n+1.0)/log(2.0),其实应该是k >= floor (log(n+1.0)/log(2.0)),还是太粗心啦)

USACO Section 2.3 Longest Prefix

| Comments

给定一字符串集合Pn, 1<=n<=200, 1<=strlen(Pn)<=10,再给定一个字符串S,1<=strlen(s)<=200000。问能用字符串集合组成的S的最长前缀的长度。

之前想的是用KMP将每一个集合中的Pn与S匹配,找出Pn能构成S子串的位置,组成200×200000的矩阵,再在这个矩阵上进行搜索。可是发现时间和内存的限制都无法满足

题目有这样的特点:S的长度很长(200000),而Pn的长度却很短(10),而且组成的字符只有A-Z二十六个。那么,Pn中有许多字符串的前缀是重合的,可否利用这一特点避免许多重复的搜索。

例如:Pn={A, AB},S=“ABA”,用P0=A对S[0]=A查找完之后,再查找S[1]=B时,能否直接转到P1=AB的B呢?

后来发现,用Trie可以存下所有Pn的信息,而且Pn中的重复前缀会放在一起,这样就避免了重复查找。(以前听过Tire,感觉很神秘,原来就是字典树啊,之前也用过啊)

USACO Section2.2 Party Lamps

| Comments

一开始是想,给定某一盏灯的最终状态,就可知道相关按钮拨动次数的奇偶。比如,state[1] = 0,我就可以知道B1+B2+B4为偶数。因此,对于给出的部分灯的最终状态,就可得到一系列的关于按钮的约束条件(可能有重复),再枚举B1~B4的情况,使其既满足B1+B2+B3+B4 = C,又满足上述约束条件,就可以得到合理的按钮拨动次数的集合了。但编程实现下来,发现C4无法满足时限,而且代码想到丑陋!

后来通过网上一些文章的提示,想到某一按钮按两次跟没有按是同样的情况,所以每种按钮只有按0次和按1次这两种情况,复杂度一下就降到24了。对于按钮的每种情况,分析以下属性:

  • 按1次按钮的总个数CBn。它代表了按钮至少按下了CBn次,因此因满足条件C >= CBn

  • CBn的奇偶性。它应该跟C的奇偶性相同

  • 已确定的部分灯的状态是否与其相符

如果满足了这三个约束条件,就是答案之一了。

////////////////////////////////////////////////////////////////////////////////////////////

看了USACO的官方分析后,发现题目中还有许多巧妙的地方:

  • 无论n和c为多大,最终灯的状态都是以长度6为循环的

  • 大于4且为偶数的c,可以转化为4;大于3且为奇数的c,可以转化为3

对于c=4,可分为:

  • 4个不同的按钮按下;

  • 2个不同的按钮按下;

  • 0个按钮按下。

对于c=3,可分为:

  • 3个不同的按钮按下;

  • 1个不同的按钮按下。

对于c=2:

  • 2个不同按钮按下;

  • 0个不同按钮按下。

对于c=1:

  • 1个不同按钮按下

查看Eclipse运行Java程序的命令行

| Comments

这些天一直试图用命令行运行Java程序,结果一直说找不到jar包中的类,改来改去,很是麻烦。在网上查找方法时,无意间在这里发现了一种途径,既然Java程序在Eclipse里面是可以正常运行的,那就看看Eclipse运行Java程序的命令到底是什么。

只要在Eclipse里面Debug相应Java程序,在Debug视图中查看主线程的Properties,就可以看到命令行了!

在OJ判题模块中使用ActiveMQ

| Comments

这两天在考虑如何在OJ中实现分布式判题,之前想到了JMS,但觉得不是很好入门。随后发现了ActiveMQ这个东西,其实就是在JMS上面有包装了一层,但是使用起来很方便。于是就做了一个样例模拟程序,以验证其可行性和效率。下图是样例程序大致思想:

image

只要开启ActiveMQ的服务,Server和Client再做一些简单的配置,就可以共享ActiveMQ中的某一消息队列(比如图中的pending-queue)。Server程序无需管理Client Node,相应工作是由ActiveMQ来完成的。queue中的消息是具有事务性的,所以Client既不会获取重复的消息,也不会漏读消息(至少按目前的观察是这样的)。这样,就实现了Server和Client之间的异步消息传递,达到分布式的效果。

样例程序的Server每隔1秒发送一个带有id的消息到pending queue;多个Client端从queue中读取消息,接着sleep一段时间。下图是样例程序的运行效果:

activemq_sample_screen

SVN资料整理

| Comments

SVN是什么?

SVN与CVS一样,是一个跨平台的软件,支持大多数常见的操作系统。作为一个开源的版本控制系统, Subversion 管理着随时间改变的数据。 这些数据放置在一个中央资料档案库 (repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动。 这样你就可以把档案恢复到旧的版本, 或是浏览文件的变动历史。Subversion 是一个通用的系统, 可用来管理任何类型的文件, 其中包括了程序源码。

用SVN需要安装哪些软件?

  • SubVersion:实现服务系统的软件。

  • TortoiseSVN:是SVN客户端程序,为windows外壳程序集成到windows资源管理器和文件管理系统的Subversion客户端。

  • Eclipse SVN Plugin:Eclipse IDE下的SVN插件。

  • …………

SVN中哪些概念?

  • Repository

版本库,用于储存所有的数据,版本库按照文件树形式储存数据-包括文件和目录,任意数量的客户端可以连接到版本库,读写这些文件。通过写数据,别人可以看到这些信息;通过读数据,可以看到别人的修改。

  • Checkout

Checkout的意思签出,虽然和Export的效果一样是把代码从服务器下载到本地,但是Checkout有验证的功能,Checkout到某处的代码,将会被TortoiseSVN监视,里面的文件可以享受各种SVN的服务。

  • Commit

假如你更新了目录中的文件,那么就可以用到commit功能。这个功能就是将你本地的文件修改记录上传到服务器上面,可以理解为上传。
他会和服务器上面的文件进行对比,假如你更新了某个文件而服务器上面也有人更新了这个文件,并且是在你checkout之后做的更新,那么它会尝试将你的更新和他人的更新进行融合(merge),假如自动merge不成功,那么报告conflict,你必须自己来手动merge,也就是把你的更新和别人的更新无冲突的写在一起。

  • Update

假如是多人合作的项目,自己不做修改的话别人也要修改,这时候就需要使用update来同步本地和服务器上的代码。
注意,假如别人删除了某个文件,那么更新之后你在本地的也会被删除。如果本地的代码已经被修改,和commit一样会先进行merge,不成功的话就会报告conflict。

  • Branches / Tags

版本控制系统的一个特性是能够把各种修改分离出来放在一个单独的开发线上。这条线被称为分支。分支经常被用来试验新的特性,而不会干扰正在修改编译器错误和 bug 的主开发线。当新的特性足够稳定之后,开发分支就可以合并回主分支里(主干)。
版本控制系统的另一个特性是能够标记特殊的版本(例如一个发布版本),所以你可以在任何时候重新建立一个特定的构建或环境。这个过程被称作标记。

  • Merge

分支用来维护独立的开发支线,在一些阶段,你可能需要将分支上的修改合并到主干,或者相反。

推荐的版本库结构

clip_image002

一个好的做法是将一个公司或者部门的所有项目的代码都放在一个版本库中,因为这样可以更好的在项目之间使用SVN的copy,diff已经merge等功能。
建议项目由3个子文件夹组成:trunk, brached, tags。trunk存放主线代码;branches存放基于主线的某一分支;而tags则存放官方的发行版本。

附:CVS,GIT,Mercurial和SVN比较

特征

CVS

Git

Mercurial

Subversion

是否原子提交

CVS: 没有. CVS提交不是原子的

Git: 是的. 提交都是原子的

Mercurial: 是的

Subversion: 提交都是原子的

文件和目录是否可以移动或重命名

CVS: 不是. 重命名不支持. 如果手动进行, 可能会损坏历史记录

Git: 支持重命名, 这是很实用的目的. git甚至能检测到重命名之后文件的改变. 尽管如此, 基于特殊的存储结构, 重命名不会被显示的记录, git能够推导出来(在实际使用中很容易做到)

Mercurial: 是的, 重命名是支持的

Subversion: 是的. 支持重命名

在移动或重命名之后智能合并

CVS: 不能. 重命名都不支持, 就不必说智能了

Git: 不支持. 细节在Git FAQ里: “Git有一个重命名的命令git mv, 但是这仅仅是为了便利. 效果和移掉某个文件, 增加另外一个文件没有任何区别”

Mercurial: 是的. 重命名之后智能合并是支持的. Mercurtial文档说:“如果我修改一个文件,而你重新命名了这个文件, 然后我们合并我们的变更, 那么我所做的修改就会被更新到根据旧文件名字而产生的新文件里(这可能就是你所期望的‘最简单的动作’, 但是不是所有版本控制系统都支持)

Subversion: 不支持. “svn help me“中提到“注意: 这个子命令相当于拷贝和删除.“并且可能有个bug

文件和目录拷贝

CVS: 不能. 拷贝不支持

Git: 不能. 拷贝不支持

Mercurtial: 是的. 支持拷贝

Subversion: 是的. 并且拷贝非常容易(O(1)). 包括产生分支

远程存储仓库的备份

CVS: 间接的. 可以使用John Polstra写的CVSup

Git: 是的. 是git的内部特征

Mercurial: 是的

Subversion: 间接的. 可以使用Chia-liang Kao的SVN::Mirror插件(好像是台湾人)或Shlomi Fish的SVN-Pusher工具

是否传递变更到父仓库

CVS: 不会

Git: 是的(Linux内核开发过程经常使用这个特征)

Mercurtial: 是的

Subversion: 是的, 使用要么是Chia-Ling Kao的SVN::Mirror脚本或者Shlomi Fish的svn-push工具

仓库权限

CVS: 很有限. “pre-commit hook scripts“能够被用来实现各种权限控制系统

Git: 请看和Git一起附带的contrib/hooks/update-paranoid. 看和svnperms类似的path_rules的代码

Mercutial: 是的. 它能够锁住仓库, 子目录或者使用hooks后的文件

Subversion: 是的. 基于HTTP权限的WebDAV-based模块能够支持基于目录级的仓库

变更集

CVS: 不是. 变更是基于文件的

Git: 是的. 是支持的, 创建他们很容易

Mercurial: 是的. 变更集是支持的

Subversion: 部分支持. 对于一次提交会隐式创建一个变更集

跟踪线性的文件历史

CVS: 是的. cvs annotate

Git: 是的.(git blame)

Mercurial: 是的(hg annotate)

Subversion: 是的(svn blame)

能够只在仓库的单目录下作用

CVS: 是的

Git: 不是. 尽管如此, 提交多少能被限制, 请看“Repository Permissions”

Mercurial: 能够基于某树的某个子集进行提交. 也有局部检出的能力

Subversion: 是的

跟踪未提交的变化

CVS: 是的. 通过cvs diff

Git: 是的. 另外, 分支在git里非常智能, 在某些工作流里能够被当成是另外一个未提交代码的存储库. 请看“git stash“命令

Mercurial: 是的. 使用hg diff

Subversion: 是的. 使用svn diff

基于单个文件的提交信息

CVS: 不是. 提交信息是基于单次变化的

Git: 是的. 提交信息基于变更集

Mercurial: 不是

Subversion: 不是. 没有这个特征

文档

CVS: 非常棒. 有很多在线的tutorials和资源, 在线的书籍. 命令行客户端也支持一个在线的帮助系统

Git: 良好. 短的帮助比较简洁难懂. man页很有分量, 但容易误解. 有很多tutorial

Mercurial: 很好. 有基于公司的书籍和wiki. 每个命令都集成了帮助

Subversion: 很好. 有一些在线的书籍和一些在线的tutorials和资源. 并且书籍是以docbook/xml写的所以很容易变换成其他格式. 命令行同样提供了在线的帮助系统

配置是否轻松

CVS: 好. 是个事实上的标准. 基于每个系统都有并且很容易配置

Git: 好. 在现有平台上二进制可用. 需要C编译器和Perl. 在windows上需要cygwin. 并有一些Unix特征

Mercurial: 非常好. 几乎所有平台都有二进制包. 从源码编译需要python2.3以上, 并且需要C编译器

Subversion: Subversion服务器需要安装在apache2模块里(如果有人希望HTTP作为底层协议的话)或使用它自身的服务器. 客户端需要Subversion特征的逻辑还有WebDAV库(针对HTTP). 安装组件很直接, 但是需要一些额外的工作(假定subversion在某些平台没有二进制包可用)

命令集

CVS: 包含了3个经常用到的命令的简单的命令集(cvs commit, cvs update和cvs checkout)和其它一些

Git: 命令集很丰富, 并且和CVS不兼容

Mercurial: 尝试模仿CVS交互方式, 但是偏离了基于不同的设计的意图

Subversion: 类CVS的命令集, 能够很容易被CVS用户使用

网络支持

CVS: 好. cvs在不同的场合使用不同的协议. 协议能够通过ssh链接的加密隧道进行

Git: 非常棒. 能够使用本地的git协议, 但也能在rsync, ssh, HTTP和HTTPS上使用

Mercurial: 非常棒. 使用HTTP或ssh. 远程访问会非常安全, 在只读网络里不需要上锁

Subversion: 非常好. Subversion服务器支持WebDAV+DeltaV(基于HTTP或HTTPS)作为底层协议, 或者它自身的协议同样能在ssh链接通道里使用.

可移植性

CVS: 好. 客户端能在UNIX, Windows和Mac OS上使用. 服务器端能在UNIX, 附有UNIX模拟层的Windows上使用

Git: 客户端运行在大多数的UNIX系统上, 但没有MS-Windows本地程序. 基于cygwin的系统看起来也能使用

Mercurial: 非常棒. 运行在基于所有能运行python的平台.仓库是兼容性的基于CPU结构和字节序的

Subversion: 非常好. 客户端和服务器端都能在UNIX, Windows和Mac OS X上运行

web接口

CVS: 是的. CVSweb, ViewVC, Chora和wwCVS

Git: 是的. Gitweb包含在发布包中

Mercurial: 是的. Web接口是内置组件

Subversion: 是的. ViewVC, SVN::Web, WebSVN, ViewSVN, mod_svn_view, Chora, Trac, SVN::RaWeb::Light, SVN Browser, Insurrection和perl_svn.另外, Subversion的apache服务也提供了一个基础的web接口

图形用户界面

CVS: 非常好. 有很多图形界面可以用: WinCVS, Cervisia(对于KDE), TortoiseCVS(Windows浏览器插件)

Git: Gitk包含在发行版中. Qqit和Git-gui工具也可使用

Mercurial: 通过hgit扩展查看历史; 检入扩展(hgct)使得提交很容易. 一些第三方的IDEs和GUI工具(如eric3, meld)有一些集成的Mercurial支持

Subversion: 非常好. 有很多GUIs可用: RapidSVN(跨平台), TortoiseSVN(Windows浏览器插件), Jsvn(java), 等. 大多数都还在开发中

生活中什么才是重要的?

| Comments

我常常问自己:“生活中什么才是重要的?”或者是“这件事对于我的生活来说真的很重要吗?”人,需要时常反省,否则就会“走得太远,却忘记了自己为何出发”。稍稍想了想,我觉得生活中对我来说至少有这几件事情是重要的。

健康

健康,我认为像是一种只要你愿意长期投资,就会有丰厚回报的股票。
每个2、3天,就找机会活动一下,对健康是绝对有好处的。没说没时间,这只是个借口,只要你认为一件事情重要,总是能抽出时间的。
另外,还应该荤素搭配、多吃水果、少吃零食。
如果还没有很好的人生规划的话,那就把保持健康作为目前的第一个计划吧。

心态


准确地说,应该是良好的心态。一位艺术家说:“你不能延长生命的长度,但你可以扩展它的宽度;你不能改变天气,但你可以左右自己的心情;你不可以控制环境,但你可以调整自己的心态。”
我不得不承认,有时自己的心态并不那么好,总是处在一个调整的状态。毕竟说的容易,做到有时去很难。不过当感到郁闷的时候,想想“接受不可改变的事情,做最好的自己”之类的话,也许会有些效果。

专业技能


为了生活、至少是生存,我们必须牢固的掌握本专业的技能。也许你会抱怨要学的东西实在是太多了,但我想真正重要的是你有没有学习新事物的能力,怎么找材料、怎么记录知识、怎么应用,这些才是关键。
(如果你的专业是计算机,不妨看一下程序员能力矩阵,也许会有些收获)

广泛知识

30岁之前,你也许还可以靠年轻和美貌来赢得成功,但在那之后,一个人的底蕴将决定他成功与否。底蕴从何而来?当然是知识。现在获取知识,有太多的途径了,网络、书籍、电视节目……每种途径都没有优劣之分,关键还是看人们对于内容的选择。比如说,看电视,你可以选择肥皂剧、综艺节目,也可以选择新闻节目、纪录片,一切都由自己来判断。
如果还是一名学生,那就要好好珍惜图书馆这个绝好的资源,抓紧时间去阅读各种类型的书籍,1~2周看一本杂书还是完全可以做到的。

人际关系

朋友多处处顺风,朋友少寸步难行。在目前的中国,良好的人际关系对我们的生活还是十分重要的。我并不是推崇开后门、走关系,但多一个朋友,就会增加一份解决问题的可能。 我感觉,我们大学生,尤其研究生,尤其是理工科的研究生,人际交往圈真的很狭窄,可能只会跟一个教研室或者一个宿舍的同学比较熟悉。多到外面走走,多交一些不是本专业、不在同年级、或者不在同一学校的朋友,应该是个不错的选择。(可说实话,这样的机会并不多,至少我们学校是这样的 :–( )