标签:style blog http 使用 strong io 问题 ar
第一题:机器翻译
模拟
可以用STL里的vector或list实现插入、删除、查找操作。
?
第二题:乌龟棋
动态规划
用 f(i, j, k, t) 表示分别用了i张卡片1、j张卡片2、k张卡片3、t张卡片4能得到的最大分数,则
f(i, j, k, t) = max{ f(i-1, j, k, t), f(i, j-1, k, t), f(i, j, k-1, t), f(i, j, k, t-1) } + a(i+j*2+k*3+t*4)
因为题目保证sum(bi) = N-1,所以最终答案就是 f(i, j, k, t), i=card(1), j=card(2), k=card(3), t=card(4).
?
第三题:关押罪犯
二分枚举答案+二分图判定
二分枚举答案和二分图都算是我的弱点,主要是因为接触的这种类型的题目不多。
既然要求「最大值的最小值」,那么只要二分枚举冲突的最大值即可。两个牢房,身处不同的牢房的犯人之间不会起冲突,明显符合二分图的性质。所以,我们可以把「有边」看做「在不同牢房」,「无边」看做「在同一个牢房」。对于mid=(l+r)/2,删去比mid小的边,那么删去的这些边是实际上存在的冲突,然后判断是不是二分图即可。如果是,那么记录下mid,然后改变枚举范围,令r=mid,继续枚举看有没有更小的满足条件的mid值;如果不是,令l=mid+1,继续枚举。
枚举有两种方法,一种是直接枚举mid的大小,另一种是在排好序的边集数组中进行枚举。第一种方法有一些无效枚举,也就是说中间过程枚举得到的值并不真实存在于图中,那么枚举次数最多log(ci)≈30;第二种方法需要进行排序,但是枚举次数最多log(M)≈17。总体来看效率差不多。
并查集
这种方法效率更高。
按照怨气的大小依次放入两个集合中,保持集合内部不冲突,直到同一个集合内产生冲突,输出即可。
?
第四题:引水入城
贪心、搜索、动态规划
这道题有多种解法,先说我自己的思路。
思路一:我最开始的做法是在第一行找出最大的,进行 Flood Fill 填充直到底行;然后找出第二大的,填充……直到能够将底行填满。该策略基于这样一个臆测:第一行里较大的数字总是能够填充到较多的底行格子。但是这样做明显不正确。
思路二:对第一行的每个格子进行 Flood Fill,找出每个顶行格子能够填充到的底行格子是哪些,第 i 个顶部格子所能达到的底部格子的集合记为B(i)。选出元素数目最大的集合Bmax,进行填充,然后调整B(i),即删去{x | x∈Bmax∩B(i) },因为如果格子已经被填充,那么将它记入元素数目中就没有意义了,也就是说元素数目 card(B(i)) 表示如果从顶部格子 i 开始填充,那么能够填充多少个未被填充的底部格子。
思路三:思路二已经有一大半正确了,但不完全正确。事实上这里不能用贪心策略,而应该用搜索。这种情况有点像2000年提高组的「单词接龙」一题,贪心策略是错误的,因为每次决策不能只依赖于上一次的状态,而是由之前所有的决策决定的,所以也不能用动态规划(如果沿用上面的这种思路)。
虽然找到了正确思路但是实现起来太过麻烦。上面的第二种思路已经可以拿到 80% 的分数了。如果要搜索,那么时间复杂度和编程复杂度都会陡增。
(以下思路来自:http://www.cnblogs.com/vb4896/p/3885441.html)
更进一步:
应该说这样的策略已经很不错了,但还是会超时。
再进一步:
用 left(i, j) 表示点 (i, j) 能覆盖的区间的左端点,right(i, j) 表示点 (i, j) 能覆盖的区间的右端点,则
left(i, j) = min{ left(xi, xj), (xi, xj) 与 (i, j) 相邻且海拔低于 (i, j) }
边界条件:left(i, j) = j,当且仅当 i=n-1, j=0
注意:当 i=n-1 时,left(i, j) 的值不可能大于 j
right(i, j) 同理。
注意还是要用一次 BFS 判断是否无解。
?
经验教训:
标签:style blog http 使用 strong io 问题 ar
原文地址:http://www.cnblogs.com/lsdsjy/p/3886733.html