zoukankan      html  css  js  c++  java
  • NOIP2018 填数游戏 搜索、DP

    LOJ


    感觉这个题十分好玩于是诈尸更博。一年之前的做题心得只有这道题还记得清楚……

    设输入为(n,m)时的答案为(f(n,m)),首先(f(n,m)=f(m,n))所以接下来默认(n leq m)。一件重要的事情是打表得到当(m>n+1)(f(n,m) = f(n,m-1)*3),证明不会。

    所以最后的问题是快速得到(f(8,9))(n,m)不大考虑搜索。

    首先考虑一些没用的剪枝:

    1、同一条对角线上填入的数字自底向上不增。这个不难反证得到。

    2、如果存在((i,j))((i+1,j-1))填入的数字相同,那么((i+1,j))((n,m))构成的矩形中一条对角线上所有位置的值必须相同。也可以反证得到。

    我们假设用了这些剪枝可以剪掉绝大部分状态,那么我们考虑如何check一个通过上述剪枝得到的答案是否合法。暴力的复杂度是(15 imes inom{15}{8})难以接受,我们考虑一些不同的思路。

    对于两条路径(P,Q),找到第一次分岔的位置,记做((x,y)),那么这两条路径中必定一条向右走、一条向下走。不失一般性地假设(P)向右走,那么(P)得到的二进制串必须比(Q)得到的二进制串小。而((x,y))是第一次分岔的位置,所以(P,Q)是否满足条件和((x+1,y))以及((x,y+1))作为起点的所有路径的串的(min)(max)有关。如果能够得到从某个点开始到达终点的所有串的(min)(max),判断合法就迎刃而解了。

    对于求以任意位置作为起点到达终点的串的(min)(max),考虑DP:设(f_{i,j,0/1})表示从((i,j))((n,m))的所有串的字典序(min / max),转移枚举下一步去到哪里。注意到DP的复杂度是(O(nm))的,相比之前有很大的提升。

    这样有可能还是跑不进(2s),但是注意到下面check合法则上面所有的剪枝都一定满足。如果可以最大化check方式在搜索中的剪枝效果,就可以更快速地搜出结果。

    那么可以这样做:按照对角线倒着填数,每一次填入一个位置之后立即计算它的DP值,判断能够判断是否合法的位置,如果某些位置作为第一次分岔的位置已经不合法,则不往下搜。不难发现这样的搜索剪枝是包含了上面的剪枝1、2的,是一个更强的剪枝。这样你就可以在LOJ上以(200ms)的速度搜出(f(8,9)),问题就完成了。

  • 相关阅读:
    zepto引用touch模块后,click失效
    cocos2dx中setContentSize与setDimensions在设置label显示区域上的区别
    convertToNodeSpace 与 convertToWorldSpace 的使用
    quick(3.2) UIListView扩展
    quick-cocos2d-x 游戏开发——StateMachine 状态机
    Lua学习笔记之字符串及模式匹配
    cocos2dx-3.x事件分发机制
    cocos2dx-Lua与Object的通讯机制
    cocos2dx-Lua与Java通讯机制
    Quick-cocos2dx容器层的使用
  • 原文地址:https://www.cnblogs.com/Itst/p/11853663.html
Copyright © 2011-2022 走看看