![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
动态规划
文章平均质量分 70
logic_nut
这个作者很懒,什么都没留下…
展开
-
pku 1458 Common Subsecquence(DP)
题目大意:给定两个字符串,求其最大的公共子串。在这里子串的定义是:Given a sequence X = ,another sequence Z = is a subsequence of X if there exists a strictly increasing sequence of indices of X such that for all j = 1,2,...,k,原创 2009-07-15 22:47:00 · 550 阅读 · 0 评论 -
最长递增子序列 LIS
对于这个问题,最直观的DP方法是cnt[i]表示以height[i]结束的最长递增子序列的元素的个数,递归方程是cnt[i]=max{height[j]换一个DP方法,以min_height[i]表示长度是i的递增子序列的第i个元素的最小高度。很明显min_height[i]是递增的,于是在搜索时可以用二分,这样总的效率可以做O(n*lgn)。详细的介绍见下面这篇转载来的文章。 什么是转载 2009-09-09 20:33:00 · 1050 阅读 · 0 评论 -
zju 1013 Great Equipment(DP)
先DP缩小范围,后枚举。 题目大意:背包问题变种。有三种物品,分别对应有weight,size,vlaue,有n个背包,每个背包也有对应的可容纳weight和可容纳size。用所有的背包,在weight和size的限制下,能得到三种物品的数量x,y,z,ans=max(x*vx+y*vy+z*vz)+extra,这里有一个比较特殊的地方在于三种物品按某一数量组合,可以得到“套装”,会有额外原创 2009-07-12 01:25:00 · 910 阅读 · 1 评论 -
google code jam PermRLE(最短哈密顿通路)
字符串压缩,转换成求哈密顿通路。问题ProblemYouve invented a slight modification of the run-length encoding (RLE) compression algorithm, called PermRLE.To compress a string, this algorithm chooses some permutat原创 2009-09-17 17:42:00 · 1395 阅读 · 0 评论 -
pku 1191 棋盘分割(DP,一点点数学)
那个式子可以化简,其实是求xi的最小平方和。DP来做。中间因为个很愚蠢的错误送了n次WA。#include #include #define _clr(a,b) memset(a,b,sizeof(a))template void get_min(T& a,T b){ if(a>b) a=b;}using namespace std;int sum[9][9];原创 2009-09-22 21:49:00 · 751 阅读 · 0 评论 -
pku 1947 Rebuilding Roads(树形DP)
第一次写树形DP,写个总结。为什么会有树形DP?每个节点的状态的值只跟他的子节点有关,兄弟节点之间是互不影响的。应该怎么来计算树形DP?深搜,先把子节点处理好,再来对当前节点进行DP。 对于pku1947这道题目,DP[i][j]表示以i为根节点、节点数为j的子树需要去除的边的最小数量,状态转移方程有DP[root][p]=DP[root.son][k]+DP[root][p-k]原创 2009-09-24 09:51:00 · 1216 阅读 · 1 评论 -
pku 3140 Contestants Division(树的划分)
题目:给定一棵树,每个节点有一个权值。任意去掉一条边会形成两颗子树,每颗子树有一个权值和,求二者相差的最小值。分析:先求出所有节点权值总和,然后以任意一个节点为根节点,深搜,求每个节点的(本身及其子节点)权值和,直接和sum比较就可以得到去除该节点和父节点之间的边时的答案。教训:又一次栽倒在vector上,因为是多数据,每次使用vector之前都需要clear。因为忘了这个WA了数次。原创 2009-09-25 23:15:00 · 934 阅读 · 0 评论 -
pku 2486 Apple Tree(树形DP,双重DP)
题目:给定一棵树,每个节点上有一个权值,从节点1出发,可以移动k步,要使经过的节点的权值和最大。分析:dp[i][j]表示从节点i出发,可以移动j步,不需要回到起点的情况;dp_back[i][j]表示从节点i出发,可以移动j步,需要回到起点的情况。首先可以确定最外层是树形DP,而里面则是一个背包的组合问题。解答:输入中给定了节点见的邻接关系,但并未制定父子关系,根据节点1是树的根,先进行原创 2009-09-25 18:45:00 · 1051 阅读 · 0 评论 -
PKU 1821 Fence(原来DP也是会超时的。。)
O(N*N*K)的DP算法还是比较容易想到的。但可以运用一个贪心策略把O(N*N)变成O(N)。这一点还是比较难的。。。 给个抄来的解题报告 题目意思就是说给你一段墙,有K个粉刷工,每个粉刷工站在一个位置,且每个粉刷工只能刷L连续长度的墙,且要包括他所在的位置,而且每个粉刷工刷一个单位的墙的价格也不一样,问怎么刷能达到最大价钱先以P为关键字对工人进行排序,使这个顺序作为动态原创 2009-10-12 11:56:00 · 1408 阅读 · 0 评论 -
pku 1848 Tree(有点麻烦的树形DP)
我是按照http://blog.sina.com.cn/s/blog_5c95cb070100d8gu.html的提示写的,大家都可以去看看,很详细。不过貌似我的代码比他的简洁点。 首先明确一点,题中的环至少需要3个顶点。因此,对于树中的每个顶点,有3种状态。f[x][0]表示以x为根的树,变成每个顶点恰好在一个环中的图,需要连的最少边数。f[x][1]表示以x为根的树,除了根x以外,原创 2009-10-09 20:42:00 · 695 阅读 · 0 评论 -
pku 1946 Cow Cycling(DP)
对于一直骑行在非队首的选手,能量消耗和距离是相等的,这给了我们用DP来处理的条件。DP[i][j]表示i个人骑行距离j的最短时间。于是有DP[i+1][d]=DP[i][k]+min_time(E-k,d-k)(0 #include #define PI 3.14159265358979323846264338327950288#define _clr(a,b) memse原创 2009-10-10 08:41:00 · 633 阅读 · 0 评论 -
pku 2411 Mondriaan's Dream(状态压缩DP)
状态压缩DP。一行一行的处理,每行对应一个状态。每一行中,每个位置有2种状态,状态0表示该位置恰好填满,状态1表示该位置对应的下一行也被填上了。如果状态next可以由状态now转换来,则DP[i+1][next]+=DP[i][now]。对于一个m*n的矩形,有m行,每行有2^n个状态,于是总的效率为O(m*2^n*2^n)。大概流程就是这个样子,细节见代码。#include原创 2009-10-09 18:27:00 · 708 阅读 · 0 评论 -
pku 3017 Cut the Sequence(贪心不是可以滥用的。。)
按着题目分类往下做,做到这一题的时候,上面说是要加数据结构的优化。不过我随便想想,发现个贪心策略,可以把复杂度降很低。我当时想的贪心策略是:假设num[i]...num[i]是一段,如果num[i]+...num[j]+num[j+1]我就按照这个思路写,提交后无限WA。在网上找了个正确的程序来手工对拍,跑了n组随机数据答案都是一样的,但只要一提交就是WA。后来,我不仅打印答案,还把中原创 2009-10-14 12:23:00 · 978 阅读 · 1 评论 -
pku 1390 Blocks(DP)
参照黑书上写的。#include #include #include #include #include #include #define PI 3.14159265358979323846264338327950288#define _clr(a,b) memset(a,b,sizeof(a))template T _abs(T a){ if(a<0) r原创 2009-10-14 12:44:00 · 705 阅读 · 0 评论 -
pku 1038 Bugs Integrated, Inc.(这题有点复杂)
写了好久,先是mle,后是tle,再是wa。这题还真是有点复杂。空间卡得很紧,我是逐个位置搜索的,如果所有状态都保存的话铁定mle,于是状态我只能一行一行的保存,所以其中还是存在重复搜索的,不过因为M很小,所以也影响不大。还有,用int保存状态会mle,改成short就好了。放置chips的时候由下往上放置,用3进制保存状态,每个位置的值的范围是0,1,2。0表示对下一行无影响,1表示占据原创 2009-10-12 20:43:00 · 1016 阅读 · 0 评论 -
pku 2978 Colored stones(枚举+DP)
枚举k种颜色的排列顺序,然后DP。k种颜色共有k!种排列,但用DFS求出这k!种排列需要k^k的时间,记录为order[]。DP的过程是这样的:DP[i][j]表示在(1-j)这一段,用order[1]到order[i]的颜色表示,至少需要移除多少个石头。于是DP[i][j]=min(DP[i-1][p]+(p+1到j这一段中颜色和order[i]不一样颜色的石头))。时间效率是k*m原创 2009-10-21 07:48:00 · 775 阅读 · 0 评论 -
pku 1948 Triangular Pastures(背包)
首先一个想法是,尽量凑出三条长度差不多的边,然后计算面积。但是这样不对,我们并不能保证那就是最优解。后来依照海伦公式写了个式子,看有没有极值什么之类的,未果。最终觉得,还是枚举比较合适。枚举第一条边的长度,我们需要快速知道第二条边和第三条边的取值的可能的组合。因为如果知道第二条边的长度,我们可以根据周长求到第三条边的长度,所以问题就变成了已知一条边,如何快速求另外一条边长度可能的取原创 2009-12-05 11:44:00 · 944 阅读 · 0 评论 -
pku 1952 BUY LOW, BUY LOWER(DP)
题意:求最长下降子序列的长度,并需要求出这种序列的个数。需要注意的是,如果两个子序列看起来一样,那么他们只能计数一次。求长度不是问题,O(n^2)的朴素DP就足够了,关键是计数。计数的话需要排除重复的,有下面这两组数据比较容易出问题。63 2 1 3 2 1 63 2 1 4 2 1 这里cost[i]表示第i天的price,s[i]表示以cost[i]结原创 2009-12-06 15:50:00 · 897 阅读 · 1 评论 -
pku 1836 Alignment(最长递增子序列)
最长递增子序列的应用。从前往后跑一遍,然后从后往前跑一遍。最后枚举。#include #include template void Get_Max(T& a,T b){ if(a<b) a=b;}using namespace std;double height[1005],temp_height;double min_height[1005];int cnt[10原创 2009-09-09 21:07:00 · 716 阅读 · 0 评论 -
pku 3267 The Cow Lexicon(很经典的字符串DP)
这个题的最大特点是待匹配的串中有杂音。如果把字典做成hash存储,采用枚举杂音点的方法来匹配,效率是O(L*2^L),这是没办法接受的。这样的问题我们一般要逆着来,把字典往待匹配的字符串里面代,效率可以做到O(L*W*25)。总之,很经典很经典。#include "string.h"#include "math.h"#include #include #include原创 2009-09-09 11:02:00 · 745 阅读 · 0 评论 -
pku 3034 Whac-a-Mole(扫描线上的点)
很经典的动态规划。关键是给定起始点和终止点,如何快速找到直线经过的整数坐标点。参考别人的博客,写了一段个人认为很赞的代码。#include "string.h"#include "math.h"#include #include #include #define MinN(x,y) ((x)<(y)?(x):(y))#define MaxN(x,y) ((x)>(y原创 2009-09-05 19:07:00 · 737 阅读 · 0 评论 -
pku 1141 Brackets Sequence(DP)
首先,大家都来鄙视我吧,这道题目我花了一天时间才勉强AC。 题目大意:输入一个由‘(’、‘ )’、‘ [’、‘ ]’ 4种符号构成的杂乱序列,通过给这个序列在恰当的位置增加一些‘(’、‘ )’、‘ [’、‘ ]’,可以使原来的序列变成regular sequence(即是通常意义上原创 2009-07-14 18:27:00 · 755 阅读 · 1 评论 -
pku 1037 A decorative fence(DP,划分)
题目大意:题目讲得很复杂,其实数学模型很简单。就是 1~n 这 n 个数,若给出一个排列 a1,a2,a3…an ,对所有 i 满足 (ai-a(i+1))(ai-a(i-1))>0 (其实也就是数按大小的波浪形排列),则该排列符合要求。各个排列之间按字典序排序。(当 n=3 时,满足条件的序列依次为( 1 , 3 , 2 ),( 2 , 1 , 3 ),( 2 , 3 , 1 ),( 3原创 2009-07-13 10:11:00 · 1235 阅读 · 2 评论 -
pku 1159 Palindrome(DP)
题目大意:给一个字符串,在其中恰当位置插入几个字符后,使该串成为回文,问最少要插入几个字符。分析:相当简单的DP。count[i][j]表示子串(第i个字符到第j个字符)变成回文后有多少个字符,数组sym存储原串。当sym[i]==sym[j]时,count[i][j]=count[i+1][j-1]+2。否则,coun原创 2009-07-15 00:52:00 · 433 阅读 · 0 评论 -
pku 1160 Post Office(DP)
题目大意:有i个村庄在一条直线上,要在这i个村庄上建立j个邮局(j)。要使各村庄到最近的邮局的距离之和最短,问这个最短距离和是多少。分析:DP。count[i][j]表示i个村庄建立j个邮局时的最短距离和。为了方便写状态转移方程,我在这里强制了第j个邮局必须建立在第i个村庄,也就是最后一个村庄必须有一个邮局。min_sum_length[i][j]表示在第i个村庄到第j个村庄范围内有原创 2009-07-16 13:31:00 · 658 阅读 · 0 评论 -
pku 1887 Testing the CATCHER(DP)
world finial 中的水题,简单DP。#include using namespace std;#define Max(x,y) (x>y?x:y)short height[10005];short count[10005];//count[n]表示以把height[n]的导弹作为最后拦截的导弹时,最大的拦截导弹数量int n,k;int main()原创 2009-07-17 10:47:00 · 420 阅读 · 0 评论 -
pku 1953 World Cup Noise(DP)
依然是DP水题,直接贴代码,这貌似是我做题以来代码最短的一次了。#include using namespace std;int count[46][2];//count[i][0]表示第i个数是0,count[i][1]表示第i个数是1int main(){ count[1][0]=count[1][1]=1; for(int i=2;i<=45;i++)原创 2009-07-17 11:13:00 · 449 阅读 · 0 评论 -
pku 1163 The Triangle(DP)
题目大意:从三角形顶部走到三角形底部,走的时候只能按对角走,问途中经过的数字和最大是多少。分析:简单DP,直接贴代码。值得提一下的是,为了省空间,状态二维数组在我是用一维数组替代的。为了方便书写,我定义了一个Tran宏。一开始,我写的是#define Tran(i,j) ((i-1)*i/2+j),代码中我使用了Tran(i-1,j),因为宏都是直接替换的,由于运算符优先级的关系原创 2009-07-16 17:12:00 · 489 阅读 · 0 评论 -
pku 1837 Balance(DP)
题意:一个杠杆,中心有支点,两边有挂钩,挂钩位置由输入给定。有一些砝码,砝码重量由输入给定。一个挂钩下可以挂多个砝码,也可以什么都不挂,但每个砝码必须都用。问有多少种组合方式,可以使杠杆平衡。 做这题,切身体会到了 DP才是王道 这话的含义。初看题目,穷举。看DISCUSS,原来是DP。像这种组合方式很多,但状态空间却不大的,一般都可以交给DP。 DP[i][j]表示放置第原创 2009-08-10 09:54:00 · 701 阅读 · 0 评论 -
pku 3252 Round Numbers(DP)
如果一个数的二进制表示中0的个数大于1的个数,这个数就是一个round numbers。给定一个范围,问这个范围内有多少个round numbers。 本来以为是位运算,有什么好办法可以快速统计出每个串中0和1的个数。自己想了一下,没什么结果。后来看到一个官方提示,用DP做。 First note that you only need to count the number o原创 2009-08-11 09:44:00 · 917 阅读 · 0 评论 -
pku 1850 Code(组合数学,DP)
题意:字符串,长度可以是1-26,串中不能有重复的字符,串中的字符必须按增序排列。字母表后的字符大于字母表前的字符,长的字符大于短的字符。给定一个字符串,问这是第几个满足要求的串。 我自己想的是用DP,0ms。做完后看discuss,其实可以直接用组合数学做,因为字母必须递增排列,所以数选好了位置就定了,这样就不是很难。后来回过头来看自己DP的代码,突然觉得和算好组合数C(n,k)原创 2009-08-11 17:21:00 · 880 阅读 · 0 评论 -
pku 1742 Coins(DP,母函数)
经典问题。给定n种硬币,每种硬币有相应的价值,并且每种硬币有一定的数量。问用这些硬币,可以组合出多少种不同的价值总和。 因为只需要记录某种价值总和是否存在,所以用bool[]存储信息即可。母函数思想和DP思想写出来的代码几乎是一致的。 #include using namespace std;bool DP[100005];struct node{ int A,原创 2009-08-14 16:31:00 · 1196 阅读 · 0 评论 -
hdu 1398 Square Coins(母函数,DP)
经典问题。有n种硬币,每种硬币都有不同的价值,若需要组合出总价值m,问有多少种组合方式。 这题中限制硬币价值都是平方数。 用母函数写出来的代码和我用DP写出来的代码长一个样子。#include using namespace std;int c1[305],c2[305],add[18];void init(){ for(int i=1;i<=17;i++)原创 2009-08-14 08:25:00 · 1185 阅读 · 0 评论 -
pku 2288 Islands and Bridges(状态压缩DP)
DescriptionGiven a map of islands and bridges that connect these islands, a Hamilton path, as we all know, is a path along the bridges such that it visits each island exactly once. On our map, th原创 2009-08-21 18:18:00 · 978 阅读 · 0 评论 -
pku 3264 Balanced Lineup(RMQ)
首先依次给定一条线段上每个点的高度。然后执行查询操作,要求输出在范围[i,j]内最高点和最低点的高度之差。 这是一个很典型的RMQ问题,关于这个问题有个很出名的DP解答方式。ST(动态规划) O(nlogn)-O(1) offline通过O(nlogn)的预计算,可以达到O(1)的查询。 关于这个算法,在百度百科里面摘抄一点:ST算法(Sparse Table),以求最原创 2009-08-30 14:22:00 · 641 阅读 · 0 评论 -
pku 3368 Frequent values(转换,RMQ)
题目:首先给定一个非降序的数列,然后进行查询操作,问范围[l,r]内出现频率最高的数字出现了多少次。个人很喜欢这道题目,因为通过巧妙的转换,能使它成为一个RMQ问题。a[i]是原数列,b[i]是转换后的数列。b[i]代表与a[i]相同的左边的节点数(包括自己),例如,(-1 -1 1 1 1 1 3 10 10 10)==>(1 2 1 2 3 4 1 1 2 3)。这时候因为一个数字原创 2009-08-30 16:42:00 · 653 阅读 · 0 评论 -
pku 1925 Spiderman(换个循环嵌套顺序)
我是用DP做的。一开始把坐标放在最外层循环,然后枚举在该坐标之后的所有building,得到下一个坐标点。TLE。后来换成把building放在外层循环,然后根据建筑物高度枚举可选的坐标点范围,ac。囧。#include "math.h"#include using namespace std;const int maxn=1000000;double start_he原创 2009-09-02 20:41:00 · 837 阅读 · 0 评论 -
pku 3280 Cheapest Palindrome(重题)
给定一个字符串,通过删除或添加字符使得其成为回文,不同字符的添加和删除会有不同的花费。 之前做过一道类似的题目,只是这里给添加删除增加了花费。通过分析可以发现,删除某个字母和添加某个字母的效果是一样的,因此我们只需要存储他们中花费较小的一个即可以了。 剩下的就是DP的工作了。 #include using namespace std;const int maxn=2原创 2009-09-01 19:29:00 · 535 阅读 · 0 评论 -
pku 2392 Space Elevator(简单背包)
注意先根据attitude排序,然后就是简单背包。#include #include using namespace std;bool height[40005];struct node{ int h,a,c;}nodes[405];bool operator<(const node& a,const node& b){ return a.a<b.a;原创 2010-04-01 09:13:00 · 628 阅读 · 0 评论