第九章 - 动态规划初步
文章平均质量分 77
专攻挖掘机炒鸡蛋算法
Hahahahaha!
展开
-
UVa #10003 Cutting Sticks (例题9-9)
9-8还没做完,感觉有点困难。回头再做这道题很好的训练了最优矩阵连乘。记忆化搜索TLE了,递推则很顺畅。递推的顺序:不能按照以前的方法递推,因为求某一个区间的解的时候要用到它子区间的解,如果按照以前的顺序递推,则子区间的解此时还没有求出来。所以先把长度为1的子区间的解求出来,这样就能求长度为2的子区间的解,然后就能求3、4...直到n+1Run Time原创 2015-02-17 16:42:49 · 720 阅读 · 0 评论 -
UVa #1025 A Spy in the Metro (例题9-1)
第一道动态规划。。书中给的状态转移的设计感觉很巧妙要注意下数组大小避免RE。Run Time: 0.032s#define UVa "LT9-1.1025.cpp" //A Spy in the Metrochar fileIn[30] = UVa, fileOut[30] = UVa;#include#include#includeusing nam原创 2015-02-13 13:49:24 · 569 阅读 · 0 评论 -
UVa #1627 Team them up! (例题9-19)
要求同一个队伍里的人互相认识,则一对互相不认识或者单方面认识的人必须被分到不同的队伍。根据后面这条规则进行分组会比较简单所以我们可以从一个人出发,递归寻找所有“存在着不互相认识”关系的人,形成一个图,再给这个图里的所有人加正反标记,保证相邻的人都有相反的标记。若存在相邻的人有着相同的标记,则输出无解。之后再根据正反标记,把他们放到相应的组里面。这样就把人分成了很多个连通块,原创 2015-03-02 16:42:37 · 1452 阅读 · 2 评论 -
UVa #10618 Tango Tango Insurrection (例题9-18)
一开始偷懒没读原题,根据白书里的描述似懂非懂的做了,WA了还纳闷半天。最好还是先读原题啊,有些看似无用的句子会给很多有用的信息每个决策要受到几个因素的影响:1、当前时间 2、左脚位置 3、右脚位置 4、上一次动了哪只脚前三个因素比较intuitive。第4个因素来自题目中的叙述:如果这次动的脚和上次的不同,则只消耗1个能量。如果这次和上次动的是同一只脚,则分三种情况,分别对原创 2015-03-03 13:43:51 · 1117 阅读 · 0 评论 -
UVa #1336 Fixing the Great Wall (例题9-21)
这道题的动态规划部分还比较直观:每次只有两个决策:向左走或者向右走。根据这个可以设计出状态:d(i,j,k)表示区间 [i,j] 已经被修复,目前处于最左端(k=0)或最右端(k=1)。另外, c 值的总和是固定的,不论决策如何,最终都是一样的。因此不用加入状态转移。不过最后不要忘了加上它;因此只用考虑 delta 就可以了。每次转移的代价就是区间 [i,j] 以外的所原创 2015-03-05 14:09:00 · 2017 阅读 · 0 评论 -
UVa #10285 Longest Run on a Snowboard (习题9-1)
第七章的熟悉的味道,加上第九章一开始的嵌套正方形因为终点不固定,似乎不方便递推最后求所有出发点的dp值的最大值。Run Time: 0.022s#define UVa "9-1.10285.cpp" //Longest Run on a Snowboardchar fileIn[30] = UVa, fileOut[30] = UVa;#i原创 2015-03-06 11:35:27 · 524 阅读 · 0 评论 -
UVa #10723 Cyborg Genes (习题9-6)
最长公共子序列模型。不同的解出现于d[i-1][j] == d[i][j-1]Run TIme: 0.009s#define UVa "9-6.10723.cpp" //Cyborg Genes#include#include#include#include#includeusing namespace std;int main()原创 2015-03-16 21:02:07 · 640 阅读 · 0 评论 -
UVa #1629 Cake slicing (习题9-3)
预处理保存下以(0,0)为左上角、(r, c)为右下角的矩形内梅子的个数,则以(r1,c1)为左上角、(r2,c2)为右下角的大矩形内梅子的个数为cnt[r2][c2] - cnt[r1-1][c2] - cnt[r2][c1-1] + cnt[r1-1][c1-1],注意边界。预处理复杂度为O(n),n为矩形格子总数。则可以在O(1)内判断某个区域内还有几个梅子。状态和状态转移方程都原创 2015-03-08 00:14:39 · 830 阅读 · 0 评论 -
UVa #12170 Easy Climb (例题9-25)
每次的调整都要依赖于上一次的决策,因此是一个多阶段决策问题。设 dp(i,j) 表示将第i个山坡高度改为j,还需要修改前i-1个山坡,所需要的代价总合。然而 j 的可能性太多(d深入分析问题,发现如果前后两个山坡的高度已经固定了,那么当前山坡调整后的高度应该属于[ max(h[i-1], h[i+1])-d , min(h[i-1], h[i+1])+d ]。如原创 2015-03-18 17:19:58 · 894 阅读 · 0 评论 -
UVa #242 Stamps and Envelope Size (习题9-5)
这动态规划简直就是个暴力法。另外这数据规模也太友善了我的做法是设 dp(i,j) 为用第 i 套邮票拼凑出 j 分钱所需要的邮票数量,递推+刷表法。遇到dp值大于S或未定义的,则可以确定此套邮票最大coverage为 j-1要留意下output格式,在题目中没说,但是在sample output中能看出来制表的痕迹。这道题惨淡的数据、大量的PE估计很多都来源于此。原创 2015-03-08 12:11:16 · 1090 阅读 · 0 评论 -
UVa #1380 A Scheduling Problem (例题9-26)
居然一次就过了。。做了两天,泪流满面啊。不过代码跑得很慢。。有机会优化一下这道题想清楚了还是很简单的,但是一开始的思路不容易理顺。下面文中我的f和g与Rujia书中的定义相反,请注意区分。题目里说,把所有的无向边去掉之后,最终答案则一定是由剩下的有向边组成的最长路径长度k或者k+1。所以我们的工作就变成了:给无向边分配方向,使得最后得到的树里,最长路径长度是否可原创 2015-03-20 15:58:00 · 1321 阅读 · 0 评论 -
UVa #1632 Alibaba (习题9-8)
区间dp,和UVa #1336 Fixing the Great Wall (例题9-21)类似。但数据规模太大,记忆化搜索会TLE,必须递推。我一开始把状态设计为dp(i,j,k)表示当前已访问区间为[i,j],且站在 i (k == 0)或 j (k==1),最少还需多少时间收集全部宝藏。同时还需要一个辅助数组来记录当前已经经历的时间,来判断是否过了deadline。这个设计很臃肿原创 2015-03-10 11:26:07 · 1020 阅读 · 2 评论 -
UVa #10163 Storage Keepers (习题9-9)
0-1背包模型,每个人的决策为装 0-j 个storage,j为当前剩余storage的数量先求出最大的L,再用这个L重新做一次dp,找出最小的YRun Time: 0.016s#define UVa "9-9.10163.cpp" //Storage Keeperschar fileIn[30] = UVa, fileOut[30] = UVa;#inclu原创 2015-03-09 17:40:46 · 517 阅读 · 0 评论 -
UVa #1625 Color Length (例题9-8)
看到后面例题9-21也用了这题的方法,把这题补上这题:在放置颜色的时候,需要判断它是不是最后一个,然后需要找到这个颜色的开始位置。如果把每个颜色的开始位置记录在状态中,状态空间将会太大但是每次放置颜色,如果有 a 种颜色还没有结束,那么这 a 种颜色结束的时候,与初始位置的距离肯定要+1。每种颜色开始和结束的位置我们可以事先算出,因此我们可以在状态转移的时候判断当前还有多少原创 2015-02-27 15:15:10 · 784 阅读 · 0 评论 -
UVa #116 Unidirectional TSP (例题9-4)
建矩阵的时候,不建议走传统的 [行,列] 的方式。为了递推的方便,最好 [列,行] 这样建。我是按照传统的方法做的,中途遇到好几次行、列混淆,dp的大小也声明反了(幸好得的是RE,如果是WA可能又要浪费很多时间)。关于打印路径:我自己按照UVa #1599 Ideal Path(例题6-20)的方法做(Rujia强烈推荐那道题的原因),虽然有一点麻烦,但是AC了。按照书中这道题给的方法原创 2015-02-16 15:43:48 · 643 阅读 · 0 评论 -
UVa #1626 Brackets sequence (例题9-10)
动态规划的意味还是挺明显的:如果子结构A、B都ok,则AB也ok。如果Aok,则(A)、[A]也ok。那么对于一个序列,我们只要扫描他所有的子结构,取子结构中dp值最小的就好了。边界条件是1、单独一个元素,这时因为无法配对,一定要加上另外一半的括号,因此dp值为1;2、一对配好对的括号,dp值为0。打印解:再次用到了Ideal Path的方法。因为只用打印任意一组解,找到第原创 2015-02-17 18:28:02 · 598 阅读 · 0 评论 -
UVa #11584 Partitioning by Palindromes (例题9-7)
线性结构上的动态规划。回文串的操作在前五章有过详细的介绍和练习。判断的方法是枚举回文串中点。因为可能要频繁的查询同一个回文串的各种子串,应该进行预处理,将结果存在数组中备用。动态规划部分,注意好边界,没有什么其他的亮点了Run Time: 0.132s#define UVa "LT9-7.11584.cpp" //Partitioning by Pali原创 2015-02-17 00:27:10 · 464 阅读 · 0 评论 -
UVa #12186 Another Crisis (例题9-12)
大家羊年新年快乐啊!这道题很适合年三十做,很涨自信。应该是马年做的最后一道题啦这道题其实真的跟动态规划有关系吗?虽然满足最优子结构,但并没有重叠子问题。因此只是一道普通的树的dfs而已。关于求最少人数的式子:(k*T - 1)/100 + 1k*T/100不需要解释。一个-1一个+1则起到了手动ceiling的功能。因为整数除法是自动floor,所以+1原创 2015-02-18 14:56:18 · 723 阅读 · 0 评论 -
UVa #12563 Jin Ge Jin Qu hao (例题9-5)
因为同时有两个要求(数量最多、数量相同时长度最长),所以要维护两个数组。因为T一定小于所有歌的长度的和,所以T上限是9678。不过如果T真的有10^9那么大应该如何处理?动态规划还适用吗?我尝试用记忆化搜索WA了,很奇怪。换成递推就直接过了。Run Time: 0.106#define UVa "LT9-5.12563.cpp" //Jin Ge Jin原创 2015-02-16 15:56:30 · 940 阅读 · 0 评论 -
UVa #11400 Lighting System Design (例题9-6)
书中的状态设计一开始不太能理解。为什么换就要全都换?为什么枚举 j 让前 j 个灯泡选取子问题的最优解,而 j+1 到 i 全部换成 i?不可以隔着换吗?对于第一个问题,起步时可以进行简单的分类讨论来探寻规律:1、如果灯泡价格比之前贵,那么我们换灯泡本身是亏钱的。只有当全部灯泡都换完,减掉一个电源的时候,我们才盈利。2、如果灯泡价格比之前还便宜,那么我们为什么不接着享受这个待遇原创 2015-02-16 21:33:14 · 533 阅读 · 0 评论 -
UVa #10934 Dropping water balloons (例题9-20)
最初的想法应该是:d(i,j) 表示用 i 个球在高度为 j 的楼里做实验,需要的最少实验次数。可是层数太大,无法作为状态。进行一下问题的转换:设 d(i,j) 表示用 i 个球做 j 次实验最高可以测试多少层楼。最后只需选取 d(k,j) >= n 的最小的 j 即可状态的转移很有意思:假设我们现在对 d(i,j) 做决策,如果气球爆了,则实验可以测定的层数等于 d(原创 2015-02-26 11:09:24 · 692 阅读 · 0 评论 -
UVa #10817 Headmaster's Headache (例题9-15)
需要注意的一个细节是 s0 s1 s2改变后,不能再用 d[i][s1][s2] 来更新dp值。最好用引用来简化代码并减少出错。Run Time: 0.549s#define UVa "LT9-15.10817.cpp" //Headmaster's Headachechar fileIn[30] = UVa, fileOut[30] = UVa;#include#in原创 2015-02-24 11:41:33 · 534 阅读 · 0 评论 -
UVa #1220 Party at Hali-Bula (例题9-13)
新年第一题,一道树上的动态规划,树的最大独立集问题。书中的介绍部分讲解了刷表法,却说有一种更实用的方法将在例题中介绍,应该说的就是这题。按照这种方法的思路,我们不必枚举所有儿子和所有孙子,只需要加一个维度来表示是否选中当前节点然后只枚举儿子。对于已经选中的节点,在记忆化搜索的递归时,将它所有儿子的这个维度设为“不选中”即可。对于不选中的节点,则对于每个儿子,原创 2015-02-23 14:26:46 · 1040 阅读 · 0 评论 -
UVa #1252 Twenty Questions (例题9-16)
2.5s低空飘过集合上的动态规划,中间状态一般就是全集的子集合。为了精确的描述状态,一般增加一个或多个维度。这道题全集就是所有的特征,中间状态就是询问了某一些特征。询问的结果则要用另一个维度来储存。动态规划的过程就是把所有可能的询问遍历一遍,在每次遍历的同时,遍历所有的询问结果的可能性。边界值及时返回、重叠子问题及时返回,避免重复运算。Run原创 2015-02-24 15:14:02 · 587 阅读 · 0 评论 -
UVa #1218 Perfect Service (例题9-14)
发现动态规划的时间复杂度等于dp数组开的大小。像这道题是n*3,复杂度为O(n)。之前有些题目是n*n,复杂度就是O(n^2)不像例题9-13,这道题本身是无根树,记忆化搜索的函数要加一个父亲节点作为参数。Run Time: 0.045s#define UVa "LT9-14.1218.cpp" //Perfect Servicechar fileIn[30] =原创 2015-02-23 16:06:40 · 634 阅读 · 0 评论 -
UVa #1347 Tour (例题9-3)
其实书里没有给出题目里全部的要求,导致一开始我感觉状态转移方程的设计不是很直观原题中给出了几个条件/要求:1. 点的横坐标distinct2. Input按照点的横坐标由小到大的顺序给出3. 从左往右走的过程中,不能“回头”,从右往左同理其实这些条件给出之后,其实书里的状态转移方程就比较容易理解了:1. 因为不能回头,所以从左往右时没走的点,回来的时候必须要原创 2015-02-15 14:10:01 · 642 阅读 · 0 评论 -
UVa #437 The Tower of Babylon (例题9-2)
记忆化搜索,前两天看mit算法导论公开课里面Charles说这个memoization不算是动态规划,递推的才是。。有机会的话回过头来写一些递推的细节上,Rujia再一次给了这样的提示:如果数据范围太大但比较稀疏,则考虑给他们编码。在第五章的例题中(UVa 12096 The SetStack Computer(例题5-5),UVa 1592 Database(例题5-9)原创 2015-02-13 14:46:38 · 510 阅读 · 0 评论 -
UVa #10118 Free Candies (习题9-2)
影响决策的条件有二:四个堆最顶端的糖的颜色,以及目前篮子里有什么颜色。可以用四个指针,分别代表四个堆目前的位置。每次决策有四种:分别从四个堆的顶部取糖果。状态则可以设计成d(p1, p2, p3, p4)代表目前指针的位置为p1, p2, p3, p4,最多可以踹走多少糖果。同时用二进制表达来代表篮子里的糖果颜色种类Run Time:0.369s#define UVa原创 2015-03-07 14:24:27 · 699 阅读 · 0 评论