UVa上未解决的题目

来自《挑战编程》和《算法竞赛入门经典(第2版)》

Programming Challenges

习题1.6.3 10137 TheTrip

  • 因为这道题的测试用例有错误,详见这里3楼的评论
  • 浮点数的题目我一向没有好感

习题4.6.3 10037 Bridge

  • 网上给出了很多贪心的解法,还有为数不多的动态规划解法,但是我没想明白

习题5.9.3 701 The Archeologists’ Dilemma

  • 如果尝试枚举E的话那么很快程序就超时了
  • 虽然我也感觉不应该暴力枚举求解,应该用对数,但是没想出来那个不等式是怎么来的(N * 10^K < 2^X < (N + 1) * 10^K)。

习题6.6.2 10213 How Many Pieces of Land ?

  • 想了好久,还是去网上查了一下,可以直接根据平面欧拉公式(F = E - V + 2)来算,因此这道题中区域总数为1 + C(n, 2) + C(n, 4)
  • 需要使用大数运算
  • 我感觉面试题不会有这种东西吧?

习题6.6.4 10157 Expressions

  • 根据书上关于Catalan数的提示,可以得到递推公式为:
    S(n ,d) = sum(S(i, j) * S(n - 2 - i, d)(0 <= i <= n - 2, 0 <= j <= d - 2))
    + sum(S(i, d - 1) * S(n - 2 - i, j)(0 <= i <= n - 2, 0 <= j <= d))
  • 根据第一个括号闭合的位置将表达式分成两部分,左边被括起来的表达式深度分成两部分来考虑:长度从0变化到n - 2,深度从0变化到d - 2,这样被括起来后最大深度为d - 1,所以右边未被括起来的部分深度必须为d,长度为n - 2 - i;长度从0变化到n - 2,深度为d - 1,这样被括起来后深度为d,所以右边深度的变化范围从0d。这样每计算一项需要2重循环,计算所有的就需要4重循环
  • 通过观察递推公式,可以将部分项合并,第一项的S(i, j)j的范围是0 <= j <= d - 2,而第二项中正好有S(i, d - 1),这样合并后就可以得到:
    S(n, d) = sum(S(i, j) * S(n - 2 - i, d)(0 <= i <= n - 2, 0 <= j <= d - 1))
    + sum(S(i, d - 1) * S(n - 2 - i, j)(0 <= i <= n - 2, 0 <= j <= d - 1))
  • 因为j只出现在乘积项的一侧,而i出现在乘积项的两侧,所以可以对j进行优化,记T(i, d - 1) = sum(i, j)(0 <= j <= d - 1),表示长度为i,深度不超过d - 1的表达式的个数,这样递推公式就又变成了:
    S(n , d) = sum(T(i, d - 1) * S(n - 2 - i, d)(0 <= i <= n - 2))
    + sum(S(i, d - 1) * T(n - 2 - i, d - 1)(0 <= i <= n - 2))
  • 然后根据刚才对T的定义,将S代换为T,可得:
    S(n, d) = sum(T(i, d - 1) * (T(n - 2 - i, d) - T(n - 2 - i, d - 1)))(0 <= i <= n - 2)
    + sum((T(i, d - 1) - T(i, d - 2)) * T(n - 2 - i, d - 1))(0 <= i <= n - 2)
    = sum(T(i, d - 1) * T(n - 2 - i, d) - T(i, d - 2) * T(n - 2 - i, d - 1))
  • 第一项表示长度为i、深度不超过d - 1每一项用括号括起来后和长度为n - 2 - i、深度不超过d进行组合,最后可得长度为n,深度不超过d的表达式数量,就是刚刚定义的T(n, d),后边一项正好为T(n, d - 1)
  • 废了一大圈劲,终于从朴素的想法推到正确的解题方法了。😦

习题6.6.5 10247 Complete Tree Labeling

  • 开始的时候一直思考如何从二层的二叉堆递推三层的二叉堆,然后从二叉堆怎么递推三叉堆,但是发现一种固定编号的二层二叉堆,变成三层的过程中会破坏二层的编号,所以从具体的某一种编号方式应该是无法递推
  • 看了一下网上的答案,如果不考虑二层的排列具体用了哪几个数字,只考虑用可以得到多少种二层的排列,那么在变成三层的时候,根一定是最小的1,然后从把剩下的数字平均分成k份,每一叉用一份,再用乘法原理进行计算

习题6.6.6 10254 The Priest Mathematician

  • 这明明是一个递推题,公式也很好写,f(n) = min(f(k) + 2^(n - k) - 1)(0 <= k < n),但是故意把数值搞大了,然后高精度计算也会超时
  • 其实它的一阶差分序列是有规律的,我佛了 😦

习题7.6.8 10089 Repackaging

  • 这题不能枚举,整数规划使用割平面好像有解法,但是也不能直接套用,看网上说用凸包,这是个啥?

习题8.6.8 10270 Bigger Square Please…

  • 这道题看起来就贼难
  • 搜索肯定是能解的。首先要把N ^ 2表示为小于N的数的平方和,然后根据这种表示方式,再尝试进行覆盖,最终取数量最小的那个
  • 根据书上的提示,深搜可以先取大的,或者是否可以用递推来解决?我也不知道
  • 第二层深搜优先放置大的,大的本身位置就少,这样或许可以剪枝?

习题10.5.7 10249 The Grand Dinner

  • 贪心或者最大流可解

习题10.5.8 10092 The Problem With the Problem Setter

  • 运筹学中的分配问题,或者称为指派问题,我记得郭强老师的《运筹学原理与算法》中给出了使用类似Floyd算法的求解方法
  • 该算法为郭老师研究发明,可惜的是没什么人知道

算法竞赛入门经典(第2版)

习题3-12 10189 Floating-Point Numbers

  • 同样是浮点数的题目

例题5-2 101 The Blocks Problem

  • 一道根据题意模拟的题目,写起来可能会很复杂

例题5-10 207 PGA Tour Prize Money
例题5-11 814 The Letter Carrier’s Rounds

  • 两道根据题意模拟的题目
  • 看起来简单,可能会有坑和难调的bug
  • 输出格式复杂

习题5-12 221 Urban Elevations

  • 浮点数的简单题目,但是还是先跳过
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章