上一次笔者简单介绍了ACMICPC程序设计竞赛的基本信.docVIP

上一次笔者简单介绍了ACMICPC程序设计竞赛的基本信.doc

  1. 1、本文档共3页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
上一次笔者简单地介绍了ACM/ICPC程序设计竞赛的基本信息和发展状况,这次则试着向大家展示一下其中一个比较简单的题目,并作出一些粗浅的分析,希望能以此让大家有个更感性的认识。 从“蛇和梯子”的问题谈对信息的过滤处理 2002年11月2日??? 阿拉伯和北非地区第5届地区赛??? 题目G??? 蛇和梯子 问题简述:“蛇和梯子”是一个在N*N(0<N<=20)的方格棋盘上进行的游戏。(见下图) 方格从1到N的平方编号。除了1号和最后1号方格,其他的格子有可能有蛇或梯子存在(蛇和梯子的数量及具体位置由输入确定,它们的数量都在100之内并且蛇和梯子不能临近放置,也就是在任何了放置两者首尾的方格之间至少还有一个未放置任何东西的格子)。开始的时候玩家把他们的标志物放在1号格子中。玩家轮流以扔骰子的方式移动他们的指示物。如果一个指示物到达了一条蛇的嘴部,则把它移回蛇的尾部。如果一个指示物到达了一个梯子的底部则将它移动到梯子的顶部。如果你是一个可以自由控制骰子的高手,现在请求出你至少需要扔几次骰子才能到达标为N^2的格子。(比如在上图所示例一中,你的方案应该是走4步到达5并由梯子上升到16,再走4步到达20并由梯子上升到33,然后走3步。这样,你一共需要扔3次骰子。而在例二中,你的方案应该是连扔4个6。) 比较容易看出,这个问题是不能用贪心算法解决的,因为你不能保证在这步到达一个数码比较大的格子就意味着最好的效率(即使是通过梯子到达了一个这步所能到达的最大号码的格子),也就是说,号码的大小并不能代表从这个格子到达终点所需要的步数上的多少,这就带给我们一个启发:蛇和梯子真的需要看成是两个东西来分别处理么?实际上确实是不需要的,蛇和梯子的本质就是我们经常在游戏中说的“单向传送点”,只不过梯子的底部是入口而顶部是出口,蛇的嘴部是入口而尾部是出口罢了,对于他们的描述完全可以选择相同的结构: struct SnakeAndLadder { ??? int from,to; }; 接下来要考虑的是解决问题的方法。贪心算法被否定之后,我们的选择可能会是搜索,对于本题所采用的搜索显然应该以广度优先的方式进行,但是稍加分析我们就会发现如果单纯地采用广度优先搜索会产生许多重复的结点,现在我们将指示物处于某格的结点简称为结点X,那么比如在例1中,第1步过后,队列中存放的结点是2,23,4,16,6,7,在第二步时,当结点2成为扩展结点时将生成结点23、4、16、6、7、8,其中只有8不存在于当前活结点队列中,即使加以判断,不把重复的结点再次加入队列中,那至少也需要对活结点队列进行搜索。实际上我们完全有更好的方法。 应该意识到,采用树状结构和搜索的方法处理问题其重要的一点是利用祖先结点的差异性来对儿子结点做不同的处理。然而在本题中,儿子结点的生成只依赖于父结点的信息而与其它祖先结点无关,所以采用树来描述这个过程其实是多余的。在走了若干步之后,对于一个特定的格子实际上只有两种状态的区分: 1、在走了这些步数之后存在一种方案使指示物位于此格中; 2、不存在这样的一种方案。 所以我们可以用一个N^2大小的数组来描述若干步之后可以到达的格子的集合,其中每一个元素描述一个格子的状态,0表示不存在一种方案到达,1表示存在至少一种方案到达。这样,我们从表示第n步状态的数组,完全可以推出表示第n+1步状态的数组,而且在第n+1步状态的数组得到之后,表示第n步状态的数组也就不再存在利用价值了。一旦数组中表示最后一个格子的元素成为1,就表示可以通过这个步数完成任务了。 比如在例1中,描述棋盘状态的数组其变化过程应该是: 描述状态 数组元素的内容(从表示第1个格的元素排列到表示最后一个格的元素) 起始状态 100000000000000000000000000000000000 第1步之后 010101100000000100000010000000000000 第2步之后 000101111111100111101111111110001000 第3步之后 000001111111111111101111111111111101 到第3步之后,数组的最后一个元素已经变为了1,这即表明存在一种方案,使得我们扔3次骰子就可以完成任务。以下是实现此算法的主要部分代码,数组下标0——size*size-1的元素分别表示了从第1格到最后一格的状态,step记录步数,obstacle是struct SnakeAndLadder的向量,描述了蛇和梯子的传送入口和出口: //初始化状态数组和步数记录 for (j=1;j<size*size;j++) ??? grid[j]=0; grid[0]=1; step=0; while (grid[size*size-1]==0) { ??? for (

文档评论(0)

yx118 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档