集训队作业陈高远演示.pptx免费

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
原创题目讲解;《WordCraft》是一个双人游戏。 游戏的唯一参数是一个字符串集D。 双方轮流进行。 轮到某玩家,他必须进行操作: 选择D中的一个串s,将D中所有s的前缀(包含s)删除。 不能操作就输了! ;该游戏一定会结束,因为每次操作D中的字符串数至少减1。 当轮到玩家,此时D是空集,那他就输了。 ;如何解决? 最基本的方法:博弈树? 可行吗? 例子:{“a”,“abc”,“b”} 状态过多:O(2^N) ;为何状态过多? 因为没有充分利用题目条件! 题目中的关键字:“前缀”。 这让我们想到了树结构。 例:{“a”,“aa”,“ac”,“acg”,“acm”};这样,每次操作就变成: 选择某一结点,删除该结点到根的路径上的所有节点。 比如,上例中,可以进行的所有操作之后的局面: ;这样,一个局面可以看作是若干个树组成。 注意到所有操作只对其中的一棵树进行,与其他树无关。 这让我们联想到游戏的和。 我们要利用SG函数来求解。;分析:如果我们能够求出任何局面的SG值,那么我们就能知道初始的局面先手是否有必胜策略。以及,先手第一步应当如何走。 例子: SG = 1 xor 3 xor 2 = 0 所以,必败!;所以,本题可分为如下部分求解: 一、建树 二、求解SG值 三、输出解;需要建的是什么树? 每个结点的父亲是它的(除了它自己外)最长的前缀。 最基本算法: O(N^2maxLen):对于每个结点,遍历集合D,找到这样的父亲。 怎么优化? 利用字典序;每个字符串的父亲如何找? 不妨令D[0] = “” : void Find_Father(int i) { int j =i-1; while(D[j]不是D[i]的前缀) j = father[j]; father[i] = j; };复杂度是多少? j = father[j] 最多进行 maxLen 次。 每次判断前缀关系要O(maxLen) 一共是O(NmaxLen^2) 优化? 判断前缀关系的优化: 计算D[i]与D[i-1]的公共前缀长度comLen即可。 之后,D[j]是D[i]的前缀当且仅当 D[j].length() Len 这样,复杂度是O(NmaxLen);从底向上依次求解。 在求解某结点i时: 枚举所有可能的操作 O(N) 计算操走后的局面的SG值 O(N) 需要预处理:每个结点的所有儿子的SG值NIM和。(xor) 所以,总复杂度是O(N^3)? 枚举所有操作时进行一次DFS,遍历时顺带计算出SG值。 ??间复杂度O(N^2);注意到这样的事实: 一个结点i为根的子树,一次操作后局面的SG值不可能大于该子树的结点数目。 重新计算复杂度: O(NmaxLen);事实上,还有一种对于每个结点不再进行一次DFS的解法。 因为从一个结点DFS,这个过程其实在从它的儿子进行DFS时完成了。 时间关系先不讲了,论文里有详细介绍。 复杂度仍然是O(NmaxLen);显然,我们进行一次DFS就可以把所有的第一步可以取的字符串列举出。 现在的问题是: 给定n个字符串,请你按某顺序将所有的串连接起来,输出字典序最小的。 比如:串“ab”,“b”,我们可以连接得到 “abb”和“bab”,我们取前者。 这道题是我很久以前想到的。 后来我发现,这道题是NOIp1998提高组第二题!!;解法就是排序,不是按照字典序排,而是: 对于两串,比较谁排在前面的时候这两个串连接起来的字典序更小。 int cmp(const void *a,const void *b) { string A = *(string*)a , B = *(string*)b; if( A+B B+A) return -1; else return 1; } ;请大家自己证明正确性。 特别地,如果这些串中没有一个是另外一个的子串,这个比较等价于比较字典序。 所以,按字典序输出即可。 我们并不需要再排序了,因为DFS时的遍历顺序就是字典序,前提是建树时按顺序来。 时间复杂度:O(NmaxLen);至此,三部分都被我们解决了!! 而给出的最优解的时间复杂度都是O(NmaxLen)。 这不可能更优,因为输入输出的复杂度和这一样。 在时间复杂度方面,完美解决啦~ ?;最初的题目是我学完SG函数的时候想到的: 给定一棵二叉树,初始时,所有结点是白的,双方轮流操作,每次选一个白结点,将该结点到根的路径上的所有结点涂黑。如果一个人无法操作,他就输了。 ;之后,想到字符串的前缀关系就是一棵树,于是,题目描述就变成现在的样子了。 最后,我又想到了那道我出的、NOIp的题目 于是在输出解的时候加上了它。 题目的模型就全部完成。 题目描述用了OI界知名的FJ的奶牛故事。 至此,题面就全都完成了。;考查

文档评论(0)

182****0328 + 关注
实名认证
内容提供者

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

1亿VIP精品文档

相关文档