
动态规划
文章平均质量分 55
动态规划算法
m0_51303687
取乎其上,得乎其中;取乎其中,得乎其下;取乎其下,则无所得矣。
展开
-
学习记录 状压DP(二)
例题3这题与上面的题目类似,不过限制了可选的总数。令dp[i][j][k]表示前i行,状态为j,共计k个。按照之前的思路,我们选定了状态j后,这一行的“国王”总数就确定为j中二进制1的个数(记为popcnt(j))了,因此前i-1行还要k-popcnt(j)个。代码如下:int tot=(n<2)?2:(1<<(n-1))+(1<<(n-2));for(int i=1; i<=n; i++) { for(int j=0; j<tot; j++) { i原创 2022-02-07 16:31:02 · 91 阅读 · 0 评论 -
学习记录 状压DP(一)
状压DP是一种在与选集合有关的DP,一般借助二进制枚举状态。下面是典型例题:例题1这题如果直接搜索,复杂度会很高。经过观察发现一旦某一行选好,那么下一行所有合法的状态就能表示出来。可以借助用二进制数[0…2m)表示某一行的所有状态,其中m为列数。(举例:二进制数00101表示选了第0和第2列)。对于任意一个状态t,若t&(t>>1)不为0则表明行内选了相邻的,是不合法状态;若它与上一行另一个状态k满足j&k不为0说明选择了两行之间有相邻的,也是不合法的。另外,如果已确定原创 2022-02-06 16:33:51 · 558 阅读 · 0 评论 -
做题记录 2022.1.12
题目链接这题乍看是贪心,好像每次取首尾两个的较小者就行。但这是错误的。考虑5 5 1 6这组数据,贪心得到的答案是42,正确答案是43。可以采用搜索,设计搜索函数为int dfs(int from,int to,int day); 返回[from,to]区间内第day天的最大值。但搜索速度太慢。而画出搜索树发现,当[from][to]确定时day也随之确定,故可以采取记忆化。int dfs(int from,int to,int day=1) { if(dp[from][to]!=0) r原创 2022-01-12 10:51:58 · 144 阅读 · 0 评论 -
树形DP学习笔记
介绍树形DP的应用,包含例题。原创 2021-12-09 18:48:56 · 261 阅读 · 0 评论 -
做题记录2021.11.19 洛谷P1103书本整理
题目链接本题很明显的DP。但转移方程如何制定是关键。去掉k本,就是选择n-k本。(不知道这里的高度有什么用 )因此可定义dp[i][j]:前i本中选j本的最小代价。很明显,∀i∈[1,n]\forall i \in[1,n]∀i∈[1,n],dp[i][1]=0。在背包问题中,我们选第i个物品时,它的前一个物品是任意的i∈[1,i−1]i \in [1,i-1]i∈[1,i−1]。但此问题需要我们知道上一个物品的宽度,因此就比较棘手。其实可以枚举上一个物品,但应注意在选了j个的前提下,上一个物品至原创 2021-11-19 20:45:13 · 377 阅读 · 0 评论 -
做题记录 洛谷P2004领地选择
题目链接这几乎是二维前缀和的模板题。众所周知,一维前缀和sumisum_isumi的定义为:对有n个数的数列,sumi=∑k=1iaisum_i=\sum \limits_{k=1}^{i}a_isumi=k=1∑iai那么,二维前缀和sumi,jsum_{i,j}sumi,j 自然就是对有n行m列的矩阵,sumi,j=∑i=1n∑j=1mai,jsum_{i,j}=\sum \limits_{i=1}^{n}\sum \limits_{j=1}^{m}a_{i,j}sumi,j=i=1∑原创 2021-11-06 15:41:15 · 250 阅读 · 0 评论 -
做题记录2021.11.3 洛谷P1521逆序对
题目链接近两天都在写一个C++的Biginteger类,一直没刷题,今天补一下。解法1.纯暴力解法 枚举所有全排列并求其逆序对,即使采用树状数组等高效方式求逆序对仍要O(nlogn∗n!)O(nlogn*n!)O(nlogn∗n!),完全不可行。解法2.动态规划定义dp[i][j]为前i个数的全排列中逆序对为j的个数。我一开始是考虑最后一个数字,但压根没有思路。正确方法是:考虑有i-1个数的序列,将第i个数插入,由于它是序列中最大的,所以插入其中最后一个位置,可以新增0个逆序原创 2021-11-03 21:03:16 · 178 阅读 · 0 评论 -
做题记录 石子合并
题目链接这个题目,我一开始的思路是这样的:先计算出前缀和sum[],对于新加进去的第i个石头堆,存在两种合并方式:1.将它与第i-1堆合并2.将前i-2堆合并,再将它并入第i-1堆中。然而这种思路就是默认了必须从1,2两个开始合并,实际上我们第一次可以合并其他的堆。所以是错误的。因此正确方法是区间DP。即枚举起点i、终点j、中间点k,然后dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]。然而如果这样枚举,就会造成需要使用没更新过的结果的情况。因此枚举长度和原创 2021-10-31 15:50:36 · 94 阅读 · 0 评论 -
做题记录 2021.10.20 被3整除的子序列
给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除答案对1e9+7取模思路:由小学数学知识可以看出是DP,但如果直接定义dp数组表示能整除的个数,状态转移就很困难。因此定义dp[i][j]=前i个数中对3的模为j的个数。只要输出dp[n][0] (n为字符串的长度)即可。dp[i][j]可分为两种情况:1.不将第i个数加进序列;2.将第i个数加进序列;因此可以得到dp[i][j]=dp[i-1][j]+dp[i-1][?]其中?处我想了很久,最终还是没想出来一个通用的式子.原创 2021-10-20 19:57:41 · 184 阅读 · 0 评论 -
做题记录2021.10.18 SequenceGame(历史问题)
来源:牛客网题目描述 由于你帮助 Alice 回答得非常好,Sept 又找到了 Bob,希望能难倒他。 他给了要求 Bob 组成一个长度为 nnn 的新的数列 aaa,其中数列 aaa 的每一个元素ai都有k个取值。求所有可能的数列a中的最长上升子序列的的最大长度。 由于 Sept 怕题目钛难,所以他答应 Bob,对于每个i,k个取值不降。输入描述: 第一行两个数 k,n,意义如题述。 接下来n行,每行k个数,即ai的k个取值。输出描述: 仅一行一个整数,即所有可能的数列 aaa 中的最长上升子序.原创 2021-10-18 16:48:41 · 413 阅读 · 0 评论 -
做题记录2021.10.15 洛谷P5662纪念品
题目链接首先看一下数据范围:首先我们可以通过最后一句话得到一个结论:本题不用开long long。下面开始分析各个数据:对于10%数据,T=1:不管有多少物品,也不管当天买入了多少,最后总是会全部卖出,而此时买入价=卖出价,所以结果为m。另有15%数据,T≤100,N=1:如果只有一件物品,那么我们可以贪心地考虑:如果某一天物品价格比前一天多,那么就在前一天尽可能多的买入,在当天全部卖出。如果物品自第x天起价格连续数日上涨,那么我们就在那一天尽可能多的买入,在达到极值的那一天卖出,以求最大效原创 2021-10-15 16:53:08 · 121 阅读 · 0 评论 -
做题记录 2021.10.11 洛谷P2426删数
题目描述有N个不同的正整数数x1, x2, … xN 排成一排,我们可以从左边或右边去掉连续的i(1≤i≤n)个数(只能从两边删除数),剩下N-i个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。每次操作都有一个操作价值,比如现在要删除从i位置到k位置上的所有的数。操作价值为|xi – xk|*(k-i+1),如果只去掉一个数,操作价值为这个数的值。 问如何操作可以得到最大值,求操作的最大价值。输入格式第一行为一个正整数N;第二行有N个用空格隔开的N个不同的正整数。输出格式一行,包.原创 2021-10-11 16:23:13 · 188 阅读 · 0 评论 -
做题记录 2021.10.10 洛谷P1439LCS
题目描述:给定n与1~n的两个全排列a,b,请计算a与b的最大公共子序列长度输入第一行:整数n第二行:序列a第三行:序列b输出一行,最大公共子序列长度样例输入51 2 3 4 53 2 1 4 5样例输出 3数据范围:1≤n≤100000由于数据范围巨大,传统的O(n2)O(n^2)O(n2)算法肯定不行。但LCS问题不像LIS那样有优化方法,所以不能按照LCS的方法做。由于给的是1~n的全排列,所以序列中所有元素都是相同的,不同的只是排列顺序罢了。而.原创 2021-10-10 16:19:39 · 103 阅读 · 0 评论 -
2021.09.16做题记录 洛谷P2690摘苹果/P6065Sumsets
题目描述很少有人知道奶牛爱吃苹果。农夫约翰的农场上有两棵苹果树(编号为1和2),每一棵树上都长满了苹果。奶牛贝茜无法摘下树上的苹果,所以她只能等待苹果从树上落下。但是,由于苹果掉到地上会摔烂,贝茜必须在半空中接住苹果(没有人爱吃摔烂的苹果)。贝茜吃东西很快,她接到苹果后仅用几秒钟就能吃完。每一分钟,两棵苹果树其中的一棵会掉落一个苹果。贝茜已经过了足够的训练,只要站在树下就一定能接住这棵树上掉落的苹果。同时,贝茜能够在两棵树之间快速移动(移动时间远少于1分钟),因此当苹果掉落时,她必定站在两棵树其.原创 2021-09-16 18:23:29 · 397 阅读 · 0 评论 -
动态规划阶段性总结3 2021.7.27
一、初值条件确定方法:以二维DP为例,通常有3种确定方式:(设两维的范围分别为[0,m] [0,n])1.设置dp[0][0…n]2.设置dp[0…m][0]3.设置dp[0][0]具体如何设置,应根据题意而定。如果发现其中一种不行,可改变为另一种。如果实在无法确定,可按照3->2->1->(1+2)的顺序依次尝试。 两层循环均从1开始。 对于计数问题,如果状态转移方程中没有 +(常数),那么初始值应当设置为原创 2021-07-27 15:58:38 · 178 阅读 · 0 评论 -
做题记录2021.7.24
乍一看,这题用贪心好像没什么问题,每次我们都找最大的t使t4<=m,并不断更新m.然而:一开始也不知道为什么,后来明白了。如果按照这个思路,那么选到后面的数字减到0的次数反而会更多,也就是说,局部最优不一定导致全局最优。然后就想用记忆化搜索,但发现数据过大会MLE(可能是我的策略有问题?),于是使用动态规划。定义dp[i]:数字i按题意分解所需的最少项,我们有:dp[i]=min{dp[i-t4]},t>=0且t4<=i按以上递推式写出代码:#include <cs.原创 2021-07-24 17:02:25 · 81 阅读 · 0 评论 -
做题记录2021.7.23
这题和01背包十分相似,但要求部分物品之间存在依赖关系。由于看到u,v,所以我就想用图表示依赖关系,建图完毕后对每个未被合并的结点进行DFS或BFS,并对路径上所有点的价值和价格相加最终得到两个和sum1和sum2,产生一个新的“物品”,其价值和价格分别为sum1和sum2,加入背包里面。进行DP时从新加入的第一个物品开始。后来发现完全没有必要这样做。直接使用一个并查集将“有关系”的物品合成一个大物品。注意如果合并时是fa[Find(x)]=Find(y),那就是v[Find(y)]+=v[Find.原创 2021-07-23 16:40:50 · 94 阅读 · 0 评论 -
做题记录2021.7.21
1.这题之前做过并进行了总结,文章链接。现在进行进一步总结,为什么控制次数的循环要在外层。我们假设控制次数的循环在内层,那人数的循环就在外层。当n=3时,很显然我们有dp(3,3)=dp(2,2)+dp(1,2),dp(1,2)=dp(2,1)+dp(3,1)。看出什么了吗?没错,对于任何一个人,dp既可能用到编号比他小,也可能用到编号比他大的人的结果,如果人数的循环在外层,那这就意味着,无论内层循环是什么顺序,dp都很可能会用到没有求解过的值,而动态规划是利用已求解过的值的,这自然无法求出正确结原创 2021-07-21 17:32:29 · 87 阅读 · 1 评论 -
做题记录2021.7.17
题目链接个人见解:对于一般的最优解问题,如果确定用DP,都可以考虑(不是一定)用类似背包的思路求解。我们知道,背包问题中有容量限制,每个物品都有重量、价值两种属性。本题似乎缺少一种。不过待求解的量是最小代价,可以把题目想象成像下面这样:有若干物品,每种物品都有若干个,每个物品有一个重量且价值为1。试计算拿到指定价值的物品至少要多大的背包。问题就转换为多重背包问题。在背包问题中,将dp数组含义改为前i种物品 价值为j时所需重量的最小值,那么我我们有如下递推式:dp[i][j]=min(dp[i原创 2021-07-17 19:08:48 · 134 阅读 · 0 评论 -
动态规划阶段总结 2021.7.15
解题步骤:确定是用DP解题;确定要用几维数组(不确定的话一般先二维),每维是什么意义,数组的值是什么意义(即确定DP策略);确定初始值;确定递推式,即状态转移方程;测试程序,如果不正确,重复上述两步直至正确为止,常用改正方法:(1)检查每层循环的数据范围;(2)检查初值,比如将0改为1等(3)检查递推式,思考应该利用“上一个(e.g:dp[i-1][j])”还是“这一个(e.g:dp[i][j])优化处理:利用“滚动数组”将二维降为一维,利用奇偶性,优化DP策略等。...原创 2021-07-15 11:05:26 · 78 阅读 · 0 评论 -
做题记录2021.7.13
首先思考一下能否用贪心求解1.每次选消耗最少的:题中所给样例即可否决此解法;2.每次在允许范围内选经验最多的:样例能通过,但如果把第二组消耗改为7,其余均改为1即无法正确求解。这就基本否决了贪心法,考虑按以下步骤用动态规划求解。Step1.数组下标与值的含义dp[i][j]代表前i个人,当前药量为j的最大经验。Step2.初值条件dp[0][0]=0。Step3.递推关系如果只能输(j<use[i]),则dp[i][j]=dp[i-1][j]+lose[i]如果能赢,则分不用药与.原创 2021-07-13 13:52:35 · 112 阅读 · 1 评论 -
一篇有纪念意义的动态规划学习笔记
题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时,拿着球没传出去的那个同学就是败者。 聪明的小蛮提出一个有趣的问题:有多少种不同的传球方法可以使得从小蛮手里开始传的球,传了m次以后,又回到小蛮手里。两原创 2021-03-08 12:43:29 · 94 阅读 · 0 评论 -
动态规划学习笔记3-背包问题(下)
个人总结:解决类似背包问题的问题,可以分为以下几个步骤:1.判断是否为背包问题以及为何种背包问题;2.判断容量、物品个数、物品重量、物品价值、使用个数(可选)分别对应题中的什么数据;3.套用相应题型的“模板”解答。例1.采药题目链接1.属于01背包问题;2.容量=时间,物品个数=草药数物品重量=采草药需要的时间物品价值=草药价值3.解答:#include <cstdio>#include <algorithm>#define MAX_T 1002#def原创 2021-03-04 19:56:57 · 110 阅读 · 1 评论 -
动态规划学习笔记2-背包(上)2021.3.2
背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkle和Hellman提出的。摘自百度百科今天学习01背包和完全背包问题1.原创 2021-03-02 20:22:12 · 93 阅读 · 0 评论 -
动态规划学习笔记1-硬币找零 2021.3.1
题意描述:假设有几种硬币,如1、3、5,并且数量无限。请找出能够组成某个数目的找零所使用最少的硬币数。输入格式:第一行两个整数数t,n,表示总金额和面值总数;第二行n个整数a1,a2…an,其中ai表示第i种硬币的面值。输出格式:最少硬币总数。如果无解,输出-1。样例输入:15 31 11 5样例输出:3思路分析:1.暴力搜索 将最小值设定为一个很大的数INF,然后设立一个递归函数dfs(int amount)求解即可,其中amount代表当前待找钱的数额,原创 2021-03-01 20:44:34 · 384 阅读 · 0 评论