Round D都要开始了, Round C还没搞定的我(D题不会搞)…另外300+名次也能拿到面试资格呢, 然而做的人却越来越少了.
Problem A. Monster Path
neta某手游…给个R*C的矩形地图, 上面用.和A标注, 走到A上有P的概率抓到妖怪, 走到.上有Q的概率抓到妖怪. 当在一个位置抓过妖怪, 下次经过就抓不到了, 给定起点坐标Rs和Cs, 需要走一条路线使得走S步获得妖怪数的期望最大, 求这个期望.
因为S最大只有9, 直接乱dfs每条路线就行了. 用数组记录一下当前位置没有抓过怪物的概率, 然后搜的时候每经过一个地点, 可计算出走这里抓到怪物的概率, 然后更新数组里当前位置没有抓过怪物的概率, 继续搜下去, 过程中记录一下概率和就是期望.
1 | //省略头文件 |
Problem B. Safe Squares
为啥我觉得这题比较难, 过的人却最多…
给一个R*C的矩形, 给K个矩形上的点, 求矩形上有多少个正方形不包含这些点中任意一个.
由于R,C,S最大能到3000, 所以需要向O(RC)上靠, 自然会想到动态规划.
如果用dp[i][j]表示前面i*j的矩形中包含的正方形数, 则dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]表示前面i*j矩形中不含当前点grid[i][j]的正方形数量. 为了求得dp[i][j], 还需要加上所有以grid[i][j]为右下角的正方形数量.
因为光枚举i和j复杂度就接近10^7, 因此需要预处理以grid[i][j]为右下角的正方形数量.
以grid[i][j]为右下角的正方形数量等于以grid[i][j]为右下角的最大合法正方形边长(从1开始取, 每个长度都能找到一个合法的正方形), 问题变成了找上方和左方最近的非法点的距离. 这个依然可以用动态规划做.
如果dpDis[i][j]表示以grid[i][j]为右下角的最大合法正方形边长, 则dpDis[i][j]要么被最接近的非法的grid[i-x][j]限制, 要么被最接近的非法的grid[i][j-x]限制, 要么和dpDis[i-1][j-1]受到相同的非法点限制. 我们用left[i][j]表示最接近的左边的非法点距离, top[i][j]表示最接近的上边的非法点距离, 则有:dpDis[i][j] = min(top[i][j], left[i][j], dpDis[i-1][j-1]).
其中left[i][j]可以很容易根据left[i-1][j]和当前位置点的合法性计算出来, top[i][j]同理.
有了dpDis[i][j]之后我们就可以完成之前的公式:dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + dpDis[i][j].
复杂度O(RC).
1 | //省略头文件 |
另一种计算dpDis[i][j]的方法是通过二分.
用数字1表示非法点, 0表示合法点, 预处理数组sum[i][j]表示矩形中1的个数.
有了sum[i][j]数组, 可以得到其中任意正方形中1的个数. 如要得到以grid[i][j]为右下角, 边长为L的正方形内1的个数, 可以用sum[i][j] - sum[i-l][j] - sum[i][j-l] + sum[i-l][j-l]求得, 然后通过二分, 查找使得1个数为0的最大边长L, 就是dpDis[i][j]的值.
Problem C. Evaluation
给N个形如a=f(b,c)的字符串, 表示变量a的值依赖b和c的值. b=g()这样的字符串表示给b一个基本值. N不超过1000, 左侧变量只会在左侧出现一次, 右侧函数内变量数不超过10. 现在可以任意安排顺序, 问这些字符串能否使得每个变量都能够求得值(是否合法).
直接把每个变量名拿出来(想念js正则), 依赖关系用单向边连起来, 构成图. 如a依赖b和c,则用c和b指向a. 然后我们根据入度关系, 用拓扑序进行更新, 从有值的点向依赖他的点更新, 最后看看是否有入度不为0的点(依赖成环)或者没有定值的点(如没有定义基本值). 复杂度为O(N)(点数不会超过11*N, 边数也不会超过10*N).
看代码的时候需要注意的是, 我代码里面本意是用val[]表示是否能求出值, 但实际上只要其依赖的变量中有一个能求出值, 其val[]就会变成true. 其需要入度计数cnt[]辅助, 当val[]为true且入度为0时才保证其依赖的数都已经有值了.
1 | //省略头文件 |
Problem D. Soldiers
彻底不会..看了份代码才想明白. 想到了就是SB题, 可惜智商不够..
给N个士兵, 每个有一个攻击力A[i]和防御力D[i], Alice和Bob轮流选且Alice先选, 每次选择的士兵攻击力或者防御力必须大于所有已经被选中的士兵, 直到不能选. 两人都身经百战, 见得多了, 问Alice是否能够比Bob多选一个士兵.
Alice多选一个士兵等价于先手走最后一步.
假设攻击力最高是x, 防御力最高是y, 可知当选择的士兵里有攻击力为x和防御力为y的士兵时就不能再选了.
如果有一个士兵的攻击力为x防御力为y, 则直接选他, 先手必胜.
如果没有这样的士兵, 则只有攻击力为x且防御力小于y的士兵和防御力为y且攻击力小于x. 对于这两类士兵, 每类至少有一个士兵, 先选到其中一个的人必败, 因为后手可以选另一类的任意一个使得先手无法再继续选择. 因此要避免先选A[i] = x且D[i] < y和A[i] < x且D[i] = y的士兵.
要避免这样的选择, 即要在A[i] < x且D[i] < y的士兵集合中走最后一步, 就形成了子问题.
整体复杂度O(n^2).
1 | //省略头文件 |