动态规划
文章平均质量分 66
Dynamic Programming
Selvaggia
这个作者很懒,什么都没留下…
展开
-
dpdpdp
贪心思想,碰到小的元素,尽可能放在前面。来了个更大的元素(大于。的第一个元素,替换掉。), 直接插入在末尾。原创 2023-07-23 22:07:44 · 241 阅读 · 0 评论 -
动态规划复习
动态规划复习1、按规矩第一步要思考的是状态表示比较容易想到的首先是一维的dp[i],但绝大多数情况下,都会携带前i个物品取得的某个属性dp[i][j],对于前i个物品,得到某属性为j的情况对于这点,我觉得可以先在大脑模拟一遍暴力搜索,看看每次搜索dfs携带的参数是否需要携带了这个属性2、还有dp[i][j]表示的,是该状态可否到达,还是到达该状态的方式总数(判断方式可以参考数据范围,如果可能的值的范围不大,可以猜测是判断某个状态是否可达)原创 2023-06-09 22:35:42 · 96 阅读 · 0 评论 -
3583. 整数分组(选数最多分成k组,最多能选几个数dp+双指针)
基础上,如果最多分为k个符合条件的分组,最多可以选出几个数(k个分组由多少数构成)原创 2023-05-13 18:00:11 · 72 阅读 · 0 评论 -
1050.鸣人的影分身(dp同n苹果放m个盘子,dfs控制搜索结果不重复⭐)
,但即使存储在map容器中,map ,int> 也需要先对vector数组排序,太过麻烦,但也同时意识到,dfs搜索不同路径,只能避免这条路的组成序列整体不同,但是对于(2,2,3)和(2,3,2),会算作两条不同的路径,为了避免两个相同的组合,试想过记录每个搜索的路径,判断两条路径的组成元素是否相同,(要想省去多组输入的初始化dp数组,应该让对dp元素赋值的语句在前。,重复的序列在排序后都归于这一种情况,于是可以避免重复。于是限制dfs,爆搜路径时,只搜索。原创 2023-04-04 16:43:28 · 395 阅读 · 0 评论 -
1222. 密码脱落(回文区间dp的状态转移)
注意:因为求的是最小,所以要先把dp置为无穷大。原创 2023-04-04 16:00:55 · 81 阅读 · 0 评论 -
包子凑数(如果gcd(a,b)=1,由于1能整除所有整数,此时ax+by能得到所有整数)
在例子4x+5y=c中,因为gcd(4,5)=1,那么不管c是什么整数,都存在整数解x、y ,也就是说答案不是INF。题目分两步, (1)判断结果是否为INF;(2)如果不是INF,统计数量。考点是“数论gcd+简单DP”。什么时候答案不是INF?也就是说,除了少数一些整数无法组合得到,其他所有的整数都能得到。因为观察gcd函数可知,两个数求公因子,一个数为0,直接返回另一个数作为公因子。首先看2个数a、b的情况,结论是:若gcd(a,b)=d,则答案不是INF。若把c看成常数,这是一个二元一次方程。原创 2023-04-03 10:48:52 · 290 阅读 · 0 评论 -
砝码称重(考虑下标越上界)
谨记:考虑下标越界时不要仅仅考虑越下界,数组上界也要考虑。为了避免考虑不周导致遗漏,需要使得递推式保持。想要不考虑上界,就把数组大小开到两倍。推到而来,根据不同途径,反推x的值。,那么原来重的一边会变成轻的一边,,即重的一边与轻的一边的差值为。依次考虑由简单到复杂的情况,、放在轻的一边 假设之前是。、放在重的一边,假设之前是。,那么重的一边还是更重,思路就没这么清晰过嘿嘿嘿。,放在重的一边自然是。原创 2023-03-22 09:26:55 · 277 阅读 · 0 评论 -
E. Palindrome-less Arrays(思维dp、拆分序列、回文)
题目:传送门分析:给出一个长度为n的数组,其中有若干个-1,需要用1~k中的数去替换所有的-1,使得数组序列中不存在长度为奇数(>3)的回文序列2 3 2, 2 2 2,…1 2 3 2 1…,观察可发现,不存在长度为奇数的回文序列等价于a[i]!=a[i+2],a[i]与a[i+1]a[i]!=a[i+2],a[i]与a[i+1]a[i]!=a[i+2],a[i]与a[i+1]没有限制关系,这样一来可以把序列拆成奇数下标和偶数下标对应元素分别组成的两个子序列最后的方案数=奇序列填补方式∗奇原创 2022-04-25 17:40:04 · 285 阅读 · 1 评论 -
砝码称重dp、bitset优化(所有元素的和、差的集合)
砝码称重好歹想到动态规划!!!该有这样动态规划的思想,并不一定需要自己考虑周全,要让程序递推前i个数是否能产生j这个数值#include <iostream>#include <algorithm>#include <set>using namespace std;const int N=105;int a[N];int n;int dp[N][100005];//该有这样动态规划的思想,并不一定需要自己考虑周全,要让程序递推 //前i个数是否能原创 2022-04-06 09:16:58 · 569 阅读 · 0 评论 -
摆动序列(爆搜、dp)
暴力极美,虽然TLE,最终归宿还是DP一、摆动序列爆搜DPdp优化一、摆动序列爆搜#include <iostream>using namespace std;const int N=10000;int m,n;//序列长m,每个数取值1~n int res=0;void dfs(int p,int x){ if(p==m){ res++; res%=N; return ; }// 接下来搜P+1位置的取值 if((p+1)&1){ for(原创 2022-04-05 12:15:27 · 283 阅读 · 0 评论 -
扰乱字符串(递归思想,区间dp做法)
扰乱字符串递归思想不管想用递归还是区间dp,首先都要搞清楚扰乱字符串基础的思想。有字符串S1,要得到它的扰乱字符串S2,可以将S1拆成【0,i),【i,n)这两段,这两段可以交换位置或者不换,合并在一起得到S1’,对于S1 ’ 合并前的那两段子字符串,对它们两个都可以进行拆分互换或不换的操作,最后得到字符串S2。但是,有一个隐含却显然的条件需要明确,那就是 对一个字符串进行拆分互换 的操作,之后得到的字符串 仍然是在这块位置、这一段。我发现许多可利用到递归的题目都是如此(最新的一道就是code fo原创 2022-04-01 20:54:50 · 1181 阅读 · 0 评论 -
区间dp、记忆化递归、分治思想
区间dp、记忆化递归、分治思想一、石子合并1区间dp模板区间dp记忆化递归做法二、快快变大区间dp记忆化递归做法一、石子合并1题意:相邻的两堆石子合并成一堆,每次合并需要的代价是合并的两队石子数量之和和哈夫曼树的区别是:加上了只能合并次昂林两个数的限制条件所有合并方式里代价的最小值最后一次一定是将两堆合并成一堆以最后一次合并的分界线分类,确定最后一次状态的集合(枚举最后一次合并)区间dp模板所有合并过程的代价之和的最小值=最后一次合并的代价+之前合并花费的代价的最小值。(所有数加上一个数原创 2022-03-30 14:23:27 · 211 阅读 · 0 评论 -
动态规划分析
一、162:Post Office#include <iostream>#include <string.h>#include <algorithm>using namespace std;const int N=305;int a[N]; int dp[N][35];//前i个村庄建了j个邮局,i个村庄到邮局的最小距离和 //假设第j个邮局建在k村庄(j<=k<=i),即前j-1个邮局建在1~k-1//最后一个邮局即第j个建在k~i之间,自原创 2022-03-25 13:01:32 · 892 阅读 · 0 评论 -
dp 之 记忆化递归
记忆化递归滑雪乘积最大plus subtract multiplySG函数原创 2022-03-15 23:26:46 · 599 阅读 · 0 评论 -
对于dp值只有0、1两种状态的背包问题
对于dp值只有0、1两种状态的背包问题,一来恰好装满型不用初始化为负无穷,因为只有0,1进行比较。二来,状态转移方程一般不再不再是朴素的max(dp[i-1][j],dp[i-1][j-w[i]]+v[i],而极有可能dp[i][j]=dp[i-1][j]; //不取if(dp[i-1][j-w[i]]) dp[i][j]+=dp[i-1][j-w[i]];或者不用if判断,dp值代表是否能到达这种状态,只要 取和不取两种决策种至少有一种可以达到该状态,dp[i][j]就为1,能达到dp[i][原创 2022-03-03 21:42:58 · 132 阅读 · 0 评论 -
bitset优化(bitset枚举一个序列所有子集)
这里写目录标题C++标准库bitset对象的初始化及操作bitset上场C++标准库bitset对象的初始化及操作// bit当作数组,下标0对应的是最右边的元素 bitset<10> bit; bit[0]=1;//0000000001 cout<<bit<<endl; bit[9]=1;//1000000001,上次的bit[0]=1噢 cout<<bit<<endl; bitset<10> b(string(原创 2022-02-28 22:28:15 · 1335 阅读 · 1 评论 -
平衡挂钩(分组背包,每组必取,取法累加)
Balance钩子分布在坐标轴上坐标已知有正有负(在平衡点原点两端),一系列重物全部要挂上去保证平衡,问平衡的挂法(//对于w[i]从a数组中选几个系数,使得相加为0(求余为0) 为了规避负数,不管是取模还是取绝对值都不行的余数为0的状态是有余数为非零数的状态递推过来的,用秋雨的方法会打乱 余数为非零数的状态,负的和正的混在一块儿了最大力矩 202015,对于相加和为负数的情况也要记录下来,不存在负数下标就把下标普遍增大7500状态递推类比 糖果 那题,这种想法特别通若某种状态存在,能通过这种原创 2022-03-01 23:13:24 · 131 阅读 · 0 评论 -
取走糖果总数是k的倍数
Balance钩子分布在坐标轴上坐标已知有正有负(在平衡点原点两端),一系列重物全部要挂上去保证平衡,问平衡的挂法(//对于w[i]从a数组中选几个系数,使得相加为0(求余为0) 为了规避负数,不管是取模还是取绝对值都不行的余数为0的状态是有余数为非零数的状态递推过来的,用秋雨的方法会打乱 余数为非零数的状态,负的和正的混在一块儿了最大力矩 202015,对于相加和为负数的情况也要记录下来,不存在负数下标就把下标普遍增大7500状态递推类比 糖果 那题,这种想法特别通若某种状态存在,能通过这种原创 2022-03-01 22:56:38 · 230 阅读 · 0 评论 -
必须使用的硬币(从后往前递推、枚举缺少这枚硬币的情况)bitset+二进制优化多重背包
4120:硬币分别存放 从前往后、从后往前的地推结果,枚举缺少第 i 枚硬币的情况#include <iostream>#include <vector>#include <algorithm>using namespace std;const int N=205;int w[N];int dp[N][10005]; int dp2[N][10005]; int main(){ int n,x; cin>>n>>x; fo原创 2022-03-01 22:47:19 · 322 阅读 · 0 评论 -
sort(a,a+m,greater<node>()); 记录负数情况处理数组下标;gcd(b,a%b);全局最优可能要舍弃局部最优
寒假周练第一轮Burglar and MatchesGoldbach's ConjectureBalanceMonitorRadar InstallationHuman Gene Functions都写的什么玩意儿Burglar and Matches题目链接#include<iostream>#include<stdio.h>#include <stdlib.h>#include<algorithm>//#include <bits/st原创 2022-01-23 00:27:03 · 1037 阅读 · 0 评论 -
01背包输出路径、完全背包、多重背包
背包问题01 Knapsack(输出路径- >选的物品)完全背包恰好占用了m这么多的背包容量???多重背包问题Ⅰ多重背包问题Ⅱ01 Knapsack(输出路径- >选的物品)#include <iostream>#include <stack>#include <string.h>using namespace std;const int N=105;int w[N];int v[N];int path[N][1005];//path[i][原创 2022-02-26 21:45:26 · 2018 阅读 · 0 评论 -
NOI**简单**英文题(dfs解多元方程,整数唯一分解定理(质因子))
这是数论中一种典型的问题:高次方程的整数解.这类问题限制条件越多,越难出现无穷多解的情况,有限解的数量也越少.对于这类问题,一般采用试数的方法.操作过程是:把所有限制转换成为数学条件,然后逐一猜测答案并进行验算.而第一步:转换为数学条件,直接关系到第二步验算的复杂程度.首先对711000000做分解素因子处理711000000=26∗32∗56∗79711000000=26 *32 *56 *79711000000=26∗32∗56∗79这里最令人注目的数字莫过于79了.把79的倍数列表如下:0.原创 2022-02-23 18:35:35 · 312 阅读 · 0 评论 -
状压dp(状态压缩,用一个数表示一组状态,降低状态表示所需维数)
这里写目录标题熄灯问题(状压+枚举) 用二进制数的大小来枚举一行开关的状态~~真~~ 状压入门题,铺棋盘(状压dp)牧场种草方法总数(草地不相邻,只能种在肥沃土地上)思路:==1、用了位运算就给我使劲打括号==2、判断状态是否合法==bitset< 1<<12 >legal ;==3、灵活使用位运算4、状压后状态范围 0 ~ (1<< n)-15、状态从0开始遍历,行啊列啊,从1开始列举熄灯问题(状压+枚举) 用二进制数的大小来枚举一行开关的状态#include &原创 2022-01-28 15:09:52 · 864 阅读 · 0 评论 -
4978:宠物小精灵之收服(0-1背包,三维 滚动到 二维)
4978:宠物小精灵之收服题目三维代码,4分wa,看个思路再接着滚动数组1、// sort(a+1,a+n+1);不用排序,递推过程中就在不断比较哪种取法能收复最多精灵2、体力值可以对m取等号using namespace std;struct node{ int ball; int energy; bool operator<(const node n)const{ if(ball==n.ball)return energy<n.energy; return bal原创 2022-01-21 13:33:37 · 640 阅读 · 0 评论 -
动态规划Dynamic programming
#include <bits/stdc++.h>using namespace std;//1、分解成子问题 2、无后效性,一种状态A只与另一种状态B的值有关,与状态B的到达方式无关 int main(int argc, char** argv) { int n; cin>>n; int a[n]; int dp[n];//存放以a[k]为结尾的序列的最长上升子序列// dp[0]=1; for(int i=0;i<n;i++){ cin>&g原创 2021-10-22 19:29:20 · 70 阅读 · 0 评论 -
3531:判断整除 膜法交配律(不要用取绝对值的啦)
3531:判断整除和2989:糖果 很相像总之这个递推就是状态转换,由已知推未知 还是由已知和未知推已知(先将未知与已知比较)两者都要初始化一些状态,因为由已知推未知嘛后者由于前提中有未知,所以除了必要的初始化,其余状态都要初始化为不存在 前者不需要初始化为不存在状态,只要稍加判断已知状态是否存在,就可以放心推出未知状态 #include <bits/stdc++.h>using namespace std;int a[10005];bool dp[10005][105]原创 2022-01-20 13:00:12 · 317 阅读 · 0 评论 -
162:Post Office
162:Post Office传送门所村庄到所有邮局的距离,分解成子问题——前i个村庄到已有的j个邮局的最小距离之和,而前i个村庄到已有的j个邮局这个问题有可以分解成子问题:前k(i>k>=j-1)个村庄到前j-1个邮局的最短距离和➕第k+1到i这所有的村庄之间建一个邮局,k+1~i个村庄到这个邮局的最小距离。后者可以先用一个数组计算出所有情况,从i到j村只建一个邮局的最小距离(建在最中间),根据递推式:s[i][j]=s[i][j-1]+a[j]-a[(i+j)/2];思维来源原创 2022-01-19 11:05:56 · 423 阅读 · 0 评论 -
2989:糖果
2989:糖果想法一:清晰讲解一清晰讲解二拟合0-1背包的想法我不懂在于,为什么最后输出的是dp[n][0]而不是dp[n][k], 换成后者则只有8分,求dp数组的循环中不取等于k而求dp[n][0]也是可以的#include <bits/stdc++.h>using namespace std;int a[105];int dp[105][105];//dp[i][j]表示对前i堆糖果,对k取模余j时 能取得的最大糖果数//与0-1背包问题进行拟合,不同在于没有给出取得原创 2022-01-17 22:26:30 · 422 阅读 · 0 评论 -
【无标题】
2985:数字组合n个整数组合成一个指定的数dp数组全部初始化为0,只初始化dp[i][0]=1;组合成0这个数有且只有一种做法, dp[i][j]=dp[i-1][j-a[i]]+dp[i-1][j];只有dp[i][j]的组成部分中是dp[x][0]才能得出组合的种数,不出现dp[x][0]则组合不成,组合方法数为0#include <bits/stdc++.h>using namespace std;int a[25];int dp[25][1005];//还要构成1005且原创 2022-01-17 19:43:27 · 141 阅读 · 0 评论 -
顾及一头一尾的序列(典型的回文)的滚动数组优化dp
顾及一头一尾的序列(典型的回文)UVA 12484:Cards(一头一尾取卡片)(动态规划,滚动数组)二维dp数组写法卡机过程两个一维数组的写法一维dp数组的写法完结撒花,和走方格的那题很像啦~UVA 12484:Cards(一头一尾取卡片)(动态规划,滚动数组)Maratona de Programação da SBC – ACM ICPC – 2012 5Problem CCardsTwo players, Alberto and Wanderley, play a game. A set原创 2021-12-31 21:05:26 · 204 阅读 · 0 评论 -
走方格(滚动数组优化dp、排列组合、递归爆搜)
#include<bits/stdc++.h>using namespace std;int main(){ int m,n; cin>>m>>n; int dp[m+1][n+1];//走到(m,n)的走法// for(int i=0;i<=m;i++){// dp[i][0]=1;// }// for(int i=0;i<=n;i++){// dp[0][i]=1;// } for(int i=1;i<=m;i++){.原创 2021-12-31 19:24:58 · 312 阅读 · 0 评论 -
2000:最长公共子上升序列
2000:最长公共子上升序列最长公共子序列公共子序列 要按照 在第一个数组中的顺序输出,必须以第一个数组中的数作为公共序列的最后一个数。所以dp数组中的每一个node类型的元素dp[i]代表的时以a【i】结尾的公共子序列的情况所以针对b数组中每一个元素,去与a数组中的所有元素进行一轮比较,这过程中,dp【i】的情况每比较一轮都可能发生变化,用currentlen记录这一轮的最长子序列情况(每一轮开始currentlen变量必须初始化,即使在循环内部重新定义这个变量node currentlen;都不行原创 2021-12-30 15:49:53 · 423 阅读 · 0 评论 -
1996:登山
1996:登山传送门1、此题坑点在于先上山后要下山2、最后求上升子序列+下降子序列的最长长度类似 1481:Maximum sum这题3、要注意的是写双重循环时内重循环 j++ 不要 写成外层循环变量 i++这种错误在写这题出现了两次,陷入死循环不得出来在此题中用这样 求下降子序列长度的方式 行不通,因为最终求的是从左到右的最长上升子序列+接着的最长下降子序列,如果这种循环方式确实能求出最长下降子序列,但是dp1[i]表示的就是从下标0到i这一段的最长下降子序列原创 2021-12-29 19:53:57 · 332 阅读 · 0 评论 -
1768:最大子矩阵
1768:最大子矩阵传送门类似于求最大子序列和的思想,关键在于把一列(处于i、j行之间的列)看作一个数用一个双重循环列举不同的行块,将行块的处理放在f函数中,等同于对普通一维数列的处理(即,将每列和视作一个数最初原型的对一维数列a求最大子序列和,dp[1]=a[1];for(int i=2;i<=n;i++){dp[i]=max(dp[i-1]+a[i],a[i]);// dp[i]=max(dp[i-1]+a[i],dp[i-1]);突然迷糊了一下,最大子序列和 子序列必须要连原创 2021-12-29 10:24:54 · 597 阅读 · 0 评论 -
1481:Maximum sum
1481:Maximum sum传送门 #include<bits/stdc++.h>using namespace std;const int MAX=50005;int a[MAX];int l[MAX];int r[MAX];int lm[MAX];int rm[MAX];int main(){ int t; cin>>t; while(t--){ int n; cin>>n; for(int i=1;i<=n;i++){原创 2021-12-28 10:45:46 · 475 阅读 · 0 评论