乱搞系列之Google Code jam 四题

Minimum Scalar Product (2008 Round1A A)

这题想到贪心的方法不难, 看看样例就想到了. 如果要证明还是要思考一番. 证明的关键思想在于采用反证法证明简单情况, 用数学归纳推广到任意情况.

Crazy Rows (2009 Round2 A)

在所有能移动到第一行的备选行当中, 选择花费最低的. 然后用同样的方法处理第二行, 第三行, 第N行.

预处理 O(N^2), 选择并移动O(N^2). 所以最后的复杂度是O(N^2).

因为多组数据, 忘了memset数组, WA了好久.

 

Bribe the Prisoners (2009 Round 1C C)

P个牢房释放Q个人的问题

首先想到的是递归解决问题, 比如dfs(a, b), 枚举i, a < i < b, 然后 dfs(a, b) = dfs(a, i) + dfs(i, b) + cost[i] 之类的. 考虑到这样可能会有重复计算的地方, 那么可以用记忆化搜索.

 

书上用的是动态规划. 我觉得把思路从递归转化到动态规划是比较好玩的事情. 有些递归是不那么好转的, 比如在解答树上的叶子的深度深浅不一的时候, 或者解答树的枝叶长得比较凌乱的时候- -||

 

所以我觉得考虑递归边界是否整齐是一个好的判断是否能转化为dp的一个好方法. 而对dp的状态进行定义是一个关键步骤, 决定了递归边界是如何界定的.

 

书上的状态定义如下

dp[i][j] : 将从A[i]号到B[i]号的囚犯(不含这两个)的连续部分的所有囚犯都释放的时候, 所需要的最少金币总数.

显然”叶子节点”是 dp[i][i+1] = 0.

目标是要求出dp[0][Q+1].

从叶子节点向上延伸一层的时候, 就是状态转移方程要写出的意思:

dp[i][j] = A[j] – A[i] – 2 + min{dp[i][k], dp[k][j]} , i < k < j.

 

 

What are Birds? (APAC Semifinal 2008 C)

有趣的赌博问题,

也是一个搜索转为dp的题目.

不写了额看电影去了.