
动态规划
playwfun
宁静致远
展开
-
腾讯九月6号红黑棋子顺序调整问题
记腾讯九月6号红黑棋子顺序调整问题。对于这样做转移的最优性质还需要继续思考。定义状态d[i][j]代表前i个黑子和前j个红子已经交换到了序列最前面且剩余棋子都按照原来顺序被交换到这i+j个棋子之后。那么d[i][j] = max(d[i+1][j] + sum(i,j,black[i+1] -1) , d[i][j+1] + sum(i,j,red[j+1] -1))sum(i,j,k)代表当前i个黑子和前j个红子已经交换到了序列最前面时,把剩余子中原来位置为K的子移动到i+j+1的位置,需原创 2020-09-08 11:22:41 · 324 阅读 · 0 评论 -
UVA 12260 (思路dp)
本题因为是博弈性质的dp 拼的就是思路,首先,咱们来看petra的策略。他只取当前最大,且存在多个最大取y值最小的那个。那么对所有的价值先按x降序排列,再按x升序排列。那么petra肯定从头一个个的取。再来看牌jan,他采取的策略是总体最优的由于前i个他最多只能取(i+1)/2 个,如前两个只能取到一个。所以以d(i,j)代表当前在i位置,要取到j个值得最优解。d( i,j ) = m原创 2015-03-23 12:51:00 · 350 阅读 · 0 评论 -
经典dp(状态之间相互l利用)
注意这里的状态只能定义为d[ i ][ j ]表示i位置还没被确定采取什么高度,还可选的高度在j -n之间、#include #include #include #include #include using namespace std;typedef long long LL;#define rep(i,n) for(int (i)=0;(i)<(n);i++)#define原创 2015-04-08 09:53:43 · 704 阅读 · 0 评论 -
HDU 4249(数位dp)
本题目,一些位置给了一个 a+b=c的表达式,其中a,b,c的一些位用?表示。问有多少种填数方式,让表达式成立。首先,要说明的是状态表示d[ i ][ j ][ k ][ p ]表示三个数的p位置为i , j ,k, 则可能有两种情况(i+j)%10==k | | ( i+j+1)%10==k,因为只有这两种情况下的状态才具有意义。那么转移,也就很清楚了,第一种情况不依赖进位,而原创 2015-04-20 16:47:53 · 466 阅读 · 0 评论 -
uva - 12093(树形dp)
就该题目而言,对状态的限定是非常重要的,先找到合适的状态涵盖所有的因素才能为状态转移打下铺垫。首先,来谈制约因素,该题目的状态必须表示父,子,孙三代边的的覆盖状态,这是为什么,当前节点已经决策,往下走对子节点决策,而子节点最多会覆盖父,子,孙,曾孙,四代边,那么转移到子节点,就至少描述下面三代的覆盖情况。状态为 0 : 父边点没被覆盖 1 : 父边被覆盖 2原创 2015-05-08 19:18:44 · 853 阅读 · 0 评论 -
山东省第六届省赛K题
#include #include #include #include #include using namespace std;typedef long long LL;const int inf = 1e9;const int N = 1010;LL d[N][N],x,y,a[N],n;bool vis[N][N];LL dp(int i,int j){ if原创 2015-05-14 18:25:05 · 491 阅读 · 0 评论 -
UVA - 1153(贪心算法)
本题目给出了一些要执行的命令,需要x单位时间,必须在y时刻之前完成,给出n条命令,问从时刻0开始,最多能够不冲突的完成多少条命令。1解体思路:首先,如果知道了,前i个的最优解耗时t,完成k个任务,那么,前i+1的最优解可以被构造出来,如果 t+a[i+1].x否则,把i+1,加入最优解队列,剔除耗时最多的一个。(这样最优解仍保持为k,只是耗时可能变少)这题目是站在最有原创 2015-06-01 19:33:50 · 700 阅读 · 0 评论 -
UVA - 10641(dp)
本题目是给定一个n(n因为是凸多边形,很容易想到,把每个灯所能照亮的范围预处理成一个连续的区间,然后排序,用背包时选择就可以了。不过有一点不同的是这里所要照亮的不是一条直线而是一个环状,所以应该从任意一个点为起始点,然后选择最优方案去包围点。因为环状处理很经典,展示代码。另外判断一个灯是否可以照亮一条特定的边的方法是:该灯与凸多边形的核心在边的两侧。#include原创 2015-05-19 10:09:01 · 450 阅读 · 0 评论 -
HDU - 5357
本题目的方法,(()()()) 要处理的大概如图所示,对于任意一个‘(’或者‘)’可以找到其第一个与之匹配的括号,那么记ai为以i为起始位置的所有情况,bi以i为结尾的所有情况,up[I]为第一个包含(Si->Smatchi)子串的第一个‘(’那么解为ans[i] = ans[up[i]] +a[i]*a[match[i]];#include using namespace st原创 2015-08-10 11:56:14 · 818 阅读 · 0 评论 -
比较好的最长公共子序列的变形
题解来自:http://hihocoder.com/discuss/question/2111题意分析给定只包含字母的两个字符串A,B,求A,B两个字符串的最长公共子序列,要求构成子序列的子串长度都必须大于等于3。比如"abcdefghijklmn"和"ababceghjklmn",其最长满足题意要求的子序列为"abcjklmn",其由公共子串"abc"和"jk转载 2015-08-24 08:43:57 · 591 阅读 · 0 评论 -
HDU 4689(思路动态规划)
题目的意思是给定一个定义 排列[5, 4, 1, 2, 3] ,字典序最小的排列相减 [ 1, 2, 3, 4, 5] ,得到的值正负为[ + + - - -];给定一个长度不超过20的加减序列,所有满足条件的序列总和。n分析:本题目数据范围小的让人认为可以用状压,但是其实过不了。定义状态d[ i ][ j ]代表走到i时前面还有j个+号未填值。为什么这样定义? 首原创 2015-08-26 19:48:59 · 758 阅读 · 0 评论 -
UVA - 1390(概率dp + hash)
一开始直接用set做状态,并且用map做记忆,直接超时。后来改成用hash值做记忆,每个点的查找时间,基本在30左右。每个状态的定义为 一个 30的数组,存的是当前联通分量中元素个数为i的个数。状态转移,只有同时选同一集合内元素会导致无法转移到下一阶段。先计算平均需多少天转移到的联通分量总数 减1的状态,然后具体计算转移到每个下一个状态需要的时间。如果 当前选择不同联通分量的概原创 2015-04-02 07:39:10 · 595 阅读 · 0 评论 -
山东省第一节省赛 C (计算几何+dp)
主要说一下状态表示。这里的状态是以d(i,j)代表以i开始,以j结尾的向量往下走还需要至少删几个点,那么最终答案就是对每个状态求一下最优值。计算几何部分应该用叉积和点积来考虑。可以发现顺时针和逆时针成立的条件正好相反。#include #include #include using namespace std;const int inf = 10000;const int N原创 2015-04-19 18:36:24 · 351 阅读 · 0 评论 -
UVA live - 4327(滑动队列优化dp)
方法同上题,对于每一层而言 d[ i ][ j ] 的最优解为max(d[I-1 ][j] , L(I,j),R(i,j));其中L(i,j)代表从i,j往左走若干位置的最优解。在这里只讨论L(I,J)的求法。L(i,j) = max( f[i-1][k] -sum[k] ) +sum[j];(其中dist(i,k)#include #include #include #原创 2015-03-23 21:33:28 · 390 阅读 · 0 评论 -
UVA - 1427(经典滑动队列优化dp)
首先,要说明滑动队列优化的情形,必须是当前位置前或者后面的一个连续区间的一个和 j 相关的func值。维护的队列为一个相对有保留价值序列,如本题维护的是func值上升而里该节点的远度下降(这也是func较低而又保留价值的原因)。#include #include #include #include #include #include #include using namesp原创 2015-03-23 20:21:50 · 536 阅读 · 0 评论 -
UVA - 1484(树形dp,最大值最小值同时维护)
#include #include #include #include #include #include #include using namespace std;#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)#define rep1(i,n) for(int (i)=1;(i)<=(n);(i)++)const int maxn原创 2015-03-31 15:56:58 · 410 阅读 · 0 评论 -
UVA 10604(进制式dp)
直接最多有6中化学药物。那么每种最多为10,且要表示改位存在要加1,采用十二进制,最大值在3000000左右,又可用状态比较少,使用记忆花搜索。#include #include #include #include #include #include #include using namespace std;const int maxk = 3501000;int d[max原创 2015-03-24 10:33:33 · 358 阅读 · 0 评论 -
UVA - 10618(条件复杂的简单dp)
这个dp 没什么可说的,状态很容易想,只是有两个地方容易出错,就是从当前位置进行转移,合法性的判断(特别注意 当右脚在左面,这这时候左脚是可以tap的)。第二个,就是计算得分。千万注意啊。#include #include #include #include #include #include using namespace std;#define rep(i,n) fo原创 2015-03-24 16:26:13 · 480 阅读 · 0 评论 -
UVA - 11600(dp,并未真正解决)
首先总结一下思路,要从起点所在已经遍历的联通分量出发,到达为遍历的联通分量(记为共k个点),需时间为 平均需要时间为n-1/k ,因为一次出发走到未被联通点的概率为k/(n-1);然后就可成功转移到其他状态,而不会出现环。把每个联通分量都抽象为一个点,每个的人数等于所在联通分量的人数。但是直接用map 存状态,并未改变状态上限 (2^30) ,如 若有 30 1 2 3 这样的数原创 2015-03-24 20:37:56 · 469 阅读 · 0 评论 -
UVA - 11691(dp 集合类)
这个题目的意思,就是给每种过敏物质最少一天的独立观察时间。直接d(s,i)代表当前已经选的集合s下,留下i天供交叉用。#include #include #include #include #include #include #include #include #include using namespace std;typedef unsigned long long原创 2015-03-25 08:45:46 · 377 阅读 · 0 评论 -
动态规划随笔
今天昨晚poj2430说说刚想到的在动态规划确定决策时的关键分析方法。状态决策必须对后面的状态不产生影响,即无后效性,要保证无后效性就必须做出足够"宽"的步伐,使得下一个被转移状态的决策没有沾染上一次走路带来的“尘土”。第二点,状态的对已有情况的依赖性。要对外界信息合理的组织,如排序等,会为状态本身附加属性,更加适合转移。原创 2015-04-07 22:02:57 · 351 阅读 · 0 评论 -
POJ 2430(状态设计类)
本题的二维状态是比较好想的吧,直接定义d[ i ][ j ] 为当前位置为i还有j个栅栏可用时的最小代价。首先按位置排序。状态转移时需要从当前出发 若 k>=1 d[ i ][ j ]可以开一个宽为1栅栏 最多将从i开始到最后一个和 i在一排j放到一个栅栏中,或者开一个宽度为2的栅栏,可延伸到最后若 k>=2 d[ i ][ j ]可同时 开两个栅栏。但该算法时间达原创 2015-04-07 21:47:02 · 498 阅读 · 0 评论 -
UVA - 12589(learning vector dp)
这题状态很好想,而且向量按斜率降序排一下,就行了,只是不用滚动数组,就超时,也是无语了、#include #include #include #include using namespace std;#define rep(i,n) for(int (i)=0;(i)<n;(i)++)#define rep1(i,x,y) for(int (i)=x;(i)<=y;(i)++)原创 2015-04-23 16:35:27 · 710 阅读 · 0 评论 -
HDU - 4276(转树形dp)
题意描述:给定一颗点上带权的树,走每条边要花费一定时间问在T分钟内从1走到n所能拿到的最大权和(n分析:数据范围很小,先dfs求出1到n至少需要多少时间,dis[ 1->n ] > T 那么走不到n。否则把总时间减掉dis[1->n],在1->n路径上的点权值变成0 ,用剩下的时间从1开始跑树形背包,原因在于除了1->n路径上的边会被跑1次,其他的边要么不跑,要么跑两边 。预处原创 2015-08-26 09:28:47 · 368 阅读 · 0 评论 -
HDU 2242(概率dp 分情况统计)
本题目的意思:给定M(M分析:首先对每只队伍,求出 至少AC一题,但AC题数比N小的概率p1,和AC至少N题的概率p;这样就可以用简单背包解决该问题,定义d[ i ][ j ] 代表前面i-1个已经决策,当前存不存在已经AC大于等于N的队伍(j=1 代表有,j = 0 代表没有)那么d[ i ][ j ] = d[ i+1 ][ 1 ] * p2[ i ] + d[ i+原创 2015-09-08 09:28:22 · 324 阅读 · 0 评论 -
HDU 5401(计数dp)
题意描述:原先设定第0颗树只有一个节点0,现在要生成第i颗数,选 ai, bi, (ai < i, bi< i) 中两个节点(ci , di)相连接,构成一个新的树,且ai中节点的编号不变, bi中的所有节点编号都要在原来的基础上+ai树的大小,这样保证编号连续,对于每颗树T而言 ,,F(T)=∑n−1i=0∑n−1j=i+1d(vi,vj)(d(vi,vj)即任意两点之间距离总和。原创 2015-08-30 12:02:00 · 927 阅读 · 0 评论 -
UVALive 4126 (ac自动机做状态类)
题意:给定最多10个长度不超过10的子串,让构造长度为n(n分析:暴力是26^25中可能性,那么怎样精简状态,可以定义d[ i ][ j ][ s ]为当前构造的串长为i且已经到达自动机j位置,已经生成的子串状态为s,接着往下构造所能生成的合法串有多少。状态转移,就是直接暴力枚举一下下一个字母是谁,在自动机中做状态转移。一开始用ac自动机做状态不是很好理解,j其实是代表着前面走原创 2015-10-09 15:40:53 · 613 阅读 · 0 评论 -
codeforces 587B(dp)
题意:这个题目的意思是给定一个长度为n(n 要求从b中选出x个数1使得这个x个数字非递减,且 下标 floor(pi) + 1 = floor( pi+1); (n*k分析:首先我们来看一下条件,数组b可以看做由很多a数组在右面拼接而成,若p1 位置为 0 -> n-1 , 那么p2 的位置为 n -> 2*n -1; 即每n个数中选一个生成新数列,且必须连续的“块”中选择原创 2015-11-10 16:10:09 · 600 阅读 · 0 评论 -
codeforces round# 296 (div1 D)(bitmasks)
本题目用bitset很容易搞定,也可用fft可惜不会:首先,统计出每个位置是否可以匹配特定字母,那么对于0 - n-1这些位置,只有当以位置为首位,且可以匹配模板串首位时,才有可能匹配,必须能在该位置的下一位匹配到模板串的第二位。用bitset即可实现。//#pragma comment(linker, "/STACK:1024000000,1024000000")#include #原创 2015-09-23 11:59:14 · 408 阅读 · 0 评论 -
CCPC - k题(dp)
本题目的意思:给定n个位置,每个位置有一个二元组,要求确定n个位置的属性(选1或者是2),使得每个二元组的1属性和2属性去最近的位置,总代价最小(代价 属性值*移动距离)分析:可以尝试如此规划,定义d[ i ][ j ]为当前修到了i位置,i位置的属性为j,那么下面的一段连续路径要修的属性为(3-j),这一段路径上的属性为(3-j)的不需要移动,剩下的要移动到两边。这个题目难得地方原创 2015-10-27 10:54:43 · 925 阅读 · 0 评论 -
codeforces 592D(树上的思路题)
题意:给出一颗n(n分析:首先我们来看一下,要把这m个点联通需要的最小联通子树的边是必须遍历到的,从其他不在该子树上的点出发,这些边也必须遍历到,那么从子树上一最远点出发最优。因为从一点出发的答案为 遍历到的边数*2 - 从该点出发的做能到达的最远点所需边数。所以从该公式可以很明显发现,在最小联通子树上的一个最远点出发最优。#include #include #inc原创 2015-11-03 08:41:32 · 618 阅读 · 0 评论 -
HDU 5677
这个问题可以先处理处一个数组A来其中A[i] 代表长度为i的回文串有多少个。那么定义状态d[i][j]代表当前已经选了i个总长度为j这个状态是否可达。问题就是个多重背包。但是当时做的时候采用了另一个思路,定义d[ i ] [ j ] [ k ] 代表当前只考虑到长度为i 及以上的 回文串选择情况时,当前还剩余j个没有选,需要这k个总长度为k;那么,最普通的转移就是o(n)就原创 2016-05-13 11:31:15 · 551 阅读 · 0 评论 -
HDU 5715
看的别人的博客写的很好点击打开链接代码如下#include #include #include #include using namespace std;typedef long long ll;#define rep(i,n) for(int i = 0 ; i<(int)n;i++)#define rep1(i,x,y) for(int i=(int)x;i<=(int原创 2016-05-31 14:45:44 · 544 阅读 · 0 评论 -
HDU 5713
dp题目首先很容易想到用d[s ][ j ] 代表集合s内的点组成j和联通集合的方式数目,转移为d[ s ][ j ] = (d[ s - s1 ][ j - 1] * f[s1]) 其中s1必须包含s中编号最小的一个元素,这是做限定,不然不好转移,f[s1 ]代表结合s1构成独立联通集合的所有方法数目。下面求f[ s 1], 计cnt[ s1 ]为s1内点互相之间所有连边的数目, 那么原创 2016-05-31 14:54:48 · 794 阅读 · 0 评论 -
codeforces 983C(dp or shortest path)
一般而言规划题目侧重于思路,shortest path 也和规划一样需要建边,规划需要dag图,最短路只需要构成图即可,然后上单源最短路算法即可,实现上可能比较复杂。例如本题目而言,首先看状态设计,d[i][j][s],代表前i个已经上电梯或已经到达,当前在i层,电梯内人员情况(空位和要到达楼层)每个状态都可以往任意楼层走,然后上下乘客,但状态之间可能来回走来走去,可用dijstra算法。进一步分...原创 2018-05-19 09:14:09 · 506 阅读 · 0 评论 -
HDU 5456(数位dp)
题意:给定n(n0 && b>0 && c >0);分析:典型的数位dp要表示减法关系,我们可以从低位到高位枚举a,b,c的当前位置是谁,走到当前位,状态的一个维度就是剩余多少火柴,和前一位需不需要借位。那么走到当前还需要控制a,b,c是不是已经走到了它的最后一位,一个3位二进制数描述,若一个数已经结束,那么当前位置只能填充0且不需要使用火柴。//#原创 2015-09-19 20:21:03 · 1462 阅读 · 0 评论 -
codeforces 589C(divide and conquer)
题意:给定一个长度不超过100的原串,让重复复制现在的串,然后向右循环移动pi次,粘贴到串的右端,重复该过程n次(每次串长都将翻倍),给定m(m分析:由于(1可以这样来看问题 记 f(i) 为从初始位置开始特定字母出现的次数,ans = f (r) - f(l-1);这样的查询,使我们想着能不能够递归60层,不分叉的统计出结果, 答案是可以的 , 注意到 深度为 i原创 2015-11-03 11:29:32 · 517 阅读 · 0 评论 -
codeforces round#322 div2 F (树形背包)
题目意思:给定一颗n(n分析:直接树形背包,找一个不是叶子的节点当根节点。d[ i ] [ j ][ k ] 代表当前在i节点,i节点分配给了k,要完成i所在子树内叶子节点分给A j个所产生的最小相邻边数。树形背包要注意的时在背包时,先前状态总是当前只考虑前面几个子树时所产生的最小值#include#include#include#include#includ原创 2015-09-29 12:52:08 · 415 阅读 · 0 评论 -
HDU - 5136(计数dp)
首先题目意思是,给定一个数N,让求树的直径上的点为N,且每个节点最多有三条连边的所有同构树的数目。首先,说一下同构树: 设 x,y为两个不同的子树 , 那么有 x - y , y - x ( - :代表相连)那么,可以对本题目,可以分奇数偶数两类分别统计。偶数,记直径上点为n的所有“ 一半”的子树数目为 tem[n/2], 那么所有的为d[n] = C(tem[n/2] ,2)原创 2015-08-04 10:04:28 · 497 阅读 · 0 评论 -
HDU 5117(简单背包dp)
本题目的意思,就是有n个灯泡,和m个开关,每个开关控制着一些灯的明亮,求所有在2^m种选择下,所有明着的灯三次方总和,定义xi 为第i盏灯的明亮情况0代表不明,1,代表名X^3 = (x1 + x2 + x3 .. xn)*(x1 + x2 + x3 .. xn)*(x1 + x2 + x3 .. xn) 所以可以分开求在三盏灯为i,j,k 时所有情况个数,也就是这三盏灯对答案的贡献。原创 2015-09-01 09:14:12 · 518 阅读 · 1 评论