dp基础大概 (8.6)
一些前言:
据说动态规划会用排序,数据结构来进行乱搞优化操作
动态规划滴核心是个啥呢?状态表示和状态转移
设状态:哪些因素会影响到最终答案,就把哪些因素用数组的维度表示出来
要充分描述,也要简洁
举个例子
计算从(1,1)走到(x,y)的方案数:
走到任意一个(p,q),只能从(p-1,q)和(p,q-1)走过来
那dp[x][y]=dp[x-1][y]+dp[x][y-1]
例一:
最长上升子序列
这个比较简单
dp[i]表示以a[i]为结尾的最长上升子序列的长度
dp[i]=max{dp[j]}+1(a[j]<a[i]&&j<i)
复杂度O(n2)
更秀一点的O(nlogn)做法:
len记录当前的最长上升子序列的长度,d[i]记录当前找到的最长上升子序列的第i项,若a[now]≤d[len],则找到第一个d[j]>a[now]的j,令d[j]=a[now],否则len++,d[len]=a[now],最后的len是最终答案,但d数组不一定是真正的最长上升子序列
dp[i][j]表示前i个位置用j个乘号的最大值
cnt(i,j)表示原数字串第i个数字到第j个数字所组成的数
dp[i][j]=max(dp[i][j],dp[k][j-1]*cnt(k+1,i))
挂饰:
看起来像个贪心(大雾)
那就排个序
按照Ai从大到小排
why?
因为挂钩越多,能挂的东西就越多
dp[i][j]=max(dp[i-1][j],dp[i-1][max(j-a[i],0)+1]+b[i])
蓝字部分是挂第i个挂钩的喜悦值
看蓝字部分的第二维,为什么+1要写在外面呢?
①:当j-a[i]+1<0时,j-a[i]肯定小于0,这时候考虑j-a[i]+1的状态是没有意义的,直接考虑手机上只有一个挂钩的情况
②:当j-a[i]+1==0时,那说明挂上i,就没有挂钩了,并且挂i只需要一个挂钩,也就是说之前手机上只有一个挂钩。如果我们写成max(j-a[i]+1,0),此时是转移到之前手机上没有挂钩的状态,是不对滴。
综上,+1要写在外面
最终答案:max{dp[n][i]}(0≤i≤n)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
char ch=getchar();
int x=;bool f=;
while(ch<''||ch>'')
{
if(ch=='-')f=;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return f?-x:x;
}
int n,dp[][];
struct G{
int a,b;
}g[];
bool cmp(G x,G y)
{
return x.a>y.a;
}
int main()
{
n=read();
for(int i=;i<=n;i++)
g[i].a=read(),g[i].b=read();
sort(g+,g++n,cmp);
memset(dp,0xcf,sizeof(dp));
dp[][]=;dp[][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
dp[i][j]=max(dp[i-][j],dp[i-][max(j-g[i].a,)+]+g[i].b);
}
}
int ans=0xcfcfcfcf;
for(int i=;i<=n;i++)
ans=max(ans,dp[n][i]);
printf("%d",ans);
}
代码
(手机好沉ρωρ)
洛谷P1233 木棍加工
看起来像求最长不上升子序列个数,但是这似乎是二维的
那我们按照l从大到小排序,再看w中有多少个不上升子序列的最少的数量
那怎么求最少的不上升子序列的数量?
dilworth定理(翻译成人话版本):
最少的不上升子序列的数量就是最长上升子序列的长度(似乎在导弹拦截里面见过)
why?
度娘大概知道
P1091合唱队形
nlogn做法qwq(导弹拦截的做法)
辣么另一种是什么呢?
我们回顾求最长上升子序列的时候,我们要找最大的dp[j],使得a[j]<a[i]
我们换个角度
就是找最大的k,使得dp[j]==k&&j<i&&a[j]<a[i]
很有可能有多个dp[j]==k
我们设置辅助数组h,h[k]为dp[j]==k中,最小的a[j]
同时h数组是单调递增的,所以查询时只要查询最大的小于a[i]的h数组的下标即可(二分查找)
为什么是单调递增的?
数据结构优化
暴力的不要不要的
据说是个二维偏序
用树状数组搞
维护前缀最大值
如果要求公共子序列的个数怎么办
dp[i][j]:第一个串的前i个字母,第二个串的前j个字母的公共子序列的个数
若s[i]==t[j],选:转移到dp[i-1][j-1],不选:dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1] (这一块是重复的)
若不相等:dp[i-1][j]+dp[i][j-1]
数据范围你猜
好吧是复杂度是n2
先来个n4的暴力
dp[i][j]:A的前i,B的前j的balabala
然后搞一遍公共子序列的dp转移,如果小于末尾的数,就再找一遍
唉唉这为毛是四维的??
在算dp[i][j]时要看dp[1][1],dp[1][2]...dp[1][j-1],dp[2][1]...一直到dp[i-1][j-1]
这样就是n2的
但是还是可以nb的继续优化
我们再设f[j]=max{dp[x][j]}(1<=x<=i-1)
当i到i+1的时候,只需要O(1)更改f[j]就可以了
这样总体就是O(n2)了
代码:
a[i]>b[j]是个什么鬼咧?
结合一下这张图。我们保证当前子序列的结尾是a[i],如果我们要更新后面的dp[i][j'],就是要求b[j']要小于a[i](当然,b[j]也要小于a[i])
tmp又是个啥?
tmp就是
红色圈里这一坨的最大值
好像似乎也许应该可能是一样的叭
dp and 容斥
zhx说小学学过(手动双关)
什么是容斥?加加减减乱搞一通
注意这里的n和m是10^8
算了我们简化一下10^6
肯定裸dp是药丸的
辣么我们用数学解决
容斥原理qwq
总路径-至少经过一个点+至少经过两个点-至少经过三个点+至少经过4个点.........
我们可以dp出容斥系数
奇数就减,偶数就加
复杂度O(t2)
窝莫得听懂
溜
来我们看看记忆化搜索
终于有一道数据范围人类的题了
如果我们只有一个dfs(x,y)表示从(x,y)走到(n,m)的距离
我们再dfs中可能多次调用同一个dfs(i,j),这样我们就可以把dfs(i,j)记下来,这就是记忆化搜索
做题步骤(雾
似乎搜索可以
哎参数不多唉
有的值重复计算了???
那就记下来
遇见duliu搜索顺序题怎么办
记忆化!!!(据说记忆化还有剪枝效果)
bzoj 3810
这是个好题
我们发现合法的一定有一条贯穿整个矩形的线
那我们就枚举贯穿线,算出左边差异度,右边差异度的最小值
设dp[i][j][4]为长为i,宽为j的矩形面对大海春暖花开状态
就是把一个矩形切成一堆小矩形
拓扑图dp
什么意思?
就是求从一个入度为0的点到达一个出度为0的点的方案数
dp[i]=∑dp[j](存在j到i的边)
我们可以边跑拓扑序,边计算dp[i]
最后出度为0的点的dp值的和就是答案
最短路图怎么建?
如果dis[u]+len[edge[i]]=dis[v],那么edge[i]就在最短路径上
然后求到T的方案数
最大子矩阵
n4乱搞
其实如果数据保证都是正整数,那就是O(n2)的
正解:先对行进行组合,选取组合中的行,把每一列上的数加起来,就变成了一行数,然后求最大子段和
所有组合中最大子段和的最大值就是答案
举个例子叭
1 2 -10 6
2 -1 3 7
3 -5 9 8
这个矩阵一共有3行
那么行的组合有{(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3)}
先对行1进行合并(其实不用合并),得到1 2 -10 6,跑最大子段和
行2和行3的省略辣(反正只有一行也没有什么可以合并的)
接下来才是真正的合并
取1,2行
1 2 -10 6
2 -1 3 7
同一列上的数字相加:
第一列:1+2=3
第二列:2-1=1
第三列:-10+3=-7
第四列:6+7=13
这样得到新的一行数: 3 1 -7 13,跑最大子段和
然后是对(1,3)(2,3)(1,2,3)这样搞,求出来所有的最大子段和中最大的那个就是答案
序列上设计dp
bzoj1003
f[i]表示前i天的最小中成本
可以套这个:
跑最短路,注意此处的最短路要保证在所有天里,起点和终点都可以互达
f[i]=min{f[j]+jl[j+1][i]*(i-j)+k}
bzoj1296
考虑只有一条木板
f[i][j]:刷到第i个格子,用了j次,最多正确粉刷的格子数
f[i][j]=max{f[k][j-1]+cnt(j+1,i)}(枚举k)
cnt:可以搞个前缀和,然后计算[j+1,i]中红色格子的数量,蓝色格子的数量,取max
再考虑有好多条木板
g[i][l]表示前i个木板一共刷了l次,最多的数量
g[i][l]=max{g[i-1][l-x]+fi[m][x]|x≤m}
什么意思呢?枚举木板i粉刷的次数,找最大值
设左括号为+1,右括号为-1
则总和为0,任意前缀和≥0
dp[i][j]前i个位置的前缀和为j的方案数
我们发现括号序列中的某些部分可以左右括号抵消
就像这样:(()))) ---------------> ))
回想一下打怪那个题
对于回血怪(a[i]-d[i]>0),我们按照d[i]升序排序,对于扣血怪(a[i]-d[i]<0),我们按照a[i]降序排序
和这个题联系一下
我们把左括号当做+1,右括号当做-1,先进行化简(左右括号互相抵消)。化简完的序列的右括号一定在左括号的左边,数量用L[i]表示。左括号的数量用R[i]表示,要选出尽可能多的括号序列,也就是要打尽可能多的怪,就按照打怪的方法排序
f[i][j]表示前i个序列,+1,-1和为j时的最长长度,len[i]是排完序后第i个括号序列的最初长度
f[i][j]=max(f[i-1][j-L[i]+R[i]]+len[j],f[i-1][j])
ans=f[n][0]
一套有趣的题
卡特兰数???(不是记搜吗(っ°Д°;)っ)
对f[n]来说,第一个左括号一定有一个与之匹配的第一个右括号,那就枚举它们中间有多少对括号。若有i对,则贡献是f[i]*f[n-1-i]
f[n]=∑f[i]*f[n-1-i](0≤i≤n-1)
上面就是卡特兰数的公式辣
其他的卡特兰数的问法:
证明:
3:左右子树不一样,设左子数的大小为i,右子树的大小就是n-i-1,乘一乘还是原来的公式
4:这里其实是求的n+2条边的凸多边形
5:把往右走当做+1,往上走当做-1,保证前缀和为0,最后和为0,还是括号匹配问题
贪心的选取每个区间的最小值
这就是那个滑块的题辣
辣么怎么用单调队列优化这个题呢?
队头维护最小值,如果最小值的下标小于当前区间的左端点就pop掉,每次插入,如果前面的值比当前插入的值大,就pop掉,这样队头一直是当前区间的最小值辣
利用辅助数组优化
.....举个例子
dp[i][0][0]--------------->dp[i+1][1][1],且第一个串是ab?:
dp[i+1][1][1]=dp[i][0][0]*f[a][b][?][0][0][1][1]
说人话:f数组处理16种转移的系数
为毛是16种?
例一:合并石子
ρωρ
poj3280
dp[l][r]表示[l,r]变为回文串的最小值
如果s[i]≠s[j],考虑[i,j-1]和[i+1,j](删掉s[i]或s[j])
dp[i][j]=min(dp[i+1][j]+add[s[i]],dp[i+1][j]+del[s[i]],dp[i][j-1]+add[s[j]],dp[i][j-1]+del[s[j]])
若s[i]==s[j],则dp[i][j]=dp[i+1][j-1]
括号最大匹配
dp[i][j]表示[i,j]内最长的合法子序列
考虑当前的括号是否匹配
没匹配:dp[i][j]=dp[i+1][j]
匹配:枚举和谁匹配
若i和k匹配,则dp[i+1][k-1]是合法的,dp[k+1][j]还要选出一个合法的子序列
所以dp[i][j]=max{dp[i+1][k-1]+dp[k+1][j]}
为毛上一个题不枚举和谁匹配呢?明明好像都是回文串的亚子
因为上一个题只能是回文串,但这个题可以是多个回文串拼起来
n≤100:枚举断点
n显然超过O(n3)允许的数据:一般来说是只考虑边界情况,不枚举断点
bzoj1900
dp[i][j]:折叠区间[i,j]的最小代价
我们可以枚举断点唉
一个折叠的区间可能由两个区间拼接而成,就枚举断点
①:自身可以压缩:找循环节的长度k(hash),dp[i][j]=dp[l][k]+2+区间长度/(k-l)+1
②:由可以压缩的子区间拼接而成,dp[i][j]=min{dp[i][k]+dp[k+1][j]}
环形问题
就是把一个环,断开成链,然后再把原来的链复制一遍接到后面
能量项链
如果它是个链:dp[i][j]=max{dp[i][k]+dp[k+1][j]+h[i]*h[k]*t[j]}
但是环可以搞出dp[4][3]这种操作,所以....
要环变链
dp[i][j]=min{dp[i][k]+dp[k+1][j]+gcd(a[i],a[j])}
似乎好像真的没什么东西
dp基础大概 (8.6)的更多相关文章
- 【专章】dp基础
知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. ----------------------------------------------------------- ...
- 【学习笔记】dp基础
知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. dp基础,主要是做题,只有练习才能彻底掌握. 洛谷P1417 烹调方案 分析:由于时间的先后会对结果有影响,所以c[i ...
- hdu 2089 不要62 (数位dp基础题)
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- poj 2955 Brackets (区间dp基础题)
We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...
- DP基础(线性DP)总结
DP基础(线性DP)总结 前言:虽然确实有点基础......但凡事得脚踏实地地做,基础不牢,地动山摇,,,嗯! LIS(最长上升子序列) dp方程:dp[i]=max{dp[j]+1,a[j]< ...
- 树形dp基础
今天来给大家讲一下数形dp基础 树形dp常与树上问题(lca.直径.重心)结合起来 而这里只讲最最基础的树上dp 1.选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程 ...
- poj2642 The Brick Stops Here(DP基础题)
比基础的多一点东西的背包问题. 链接:POJ2642 大意:有N种砖,每种花费p[i],含铜量c[i],现需要用M种不同的砖融成含铜量在Cmin到Cmax之间(可等于)的砖,即这M种砖的含铜量平均值在 ...
- UVA103 dp基础题,DAG模型
1.UVA103 嵌套n维空间 DAG模型记忆化搜索,或者 最长上升子序列. 2.dp[i]=max( dp[j]+1),(第i个小于第j个) (1) //DAG模型记忆化搜索 #include< ...
- hdu 1561 The more, The Better(树形dp,基础)
The more, The Better Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
随机推荐
- ubuntu14 文件夹添加/删除书签
1. 打开文件管理,进入你要添加书签的目录 2. 把鼠标移到顶部选择“Bookmarks" 3. 这是文件管理左侧可以看到 4. 右键可以选择删除
- Tomcat域名与服务器多对多配置
参考: https://www.cnblogs.com/yueshutong/p/9381566.html
- 小白学Python——Matplotlib 学习(1)
众所周知,通过数据绘图,我们可以将枯燥的数字转换成容易被人们接受的图表,从而让人留下更加深刻的印象.而大多数编程语言都有自己的绘图工具,matplotlib就是基于Python的绘图工具包,使用它我们 ...
- 好用的 Puppeteer 辅助工具 Puppeteer Recorder
Puppeteer Puppeteer 是一个Node库,它提供了一个高级API来控制DevTools协议上的Chrome或Chromium,常用于爬虫.自动化测试等,你在浏览器手动完成的大多数事情都 ...
- Restful风格API中用put还是post做新增操作有什么区别?
Restful风格API中用put还是post做新增操作有什么区别? 转 头条面试归来,有些话想和Java开发者说!>>> 这个是华为面试官问我的问题,回来我找了很多资料,想验证这个 ...
- PCIeの数据链路层与物理层详解
数据链路层(DLL,Data Link Layer)的主要作用是进行链路管理(Link Management).TLP错误校验.Flow Control(流控制)和Link功耗管理.不仅可以接收发送来 ...
- Python 通过RSA实现license验证设备指纹与有效期
前言 本文使用RSA非对称加密算法,了解详情请访问: RSA 非对称加密算法简述 https://blog.csdn.net/ctwy291314/article/details/88821838 P ...
- 基于maven搭建hibernate运行环境
准备案例需要的数据库表和测试数据 建表语句: create table DEPARTMENT ( DEPT_ID integer not null, DEPT_NAME ) not null, DEP ...
- Qt Creator的初步使用
http://c.biancheng.net/view/1804.html 启动 Qt Creator,出现如图 1 所示的主窗口: 图 1 Qt Creator主窗口 Qt Creator 的界面很 ...
- Jmeter--逻辑控制之if控制器(转)
一.背景 在实际工作中,当使用Jmeter做性能脚本或者接口脚本时,有可能会遇到需要对不同的条件做不同的操作,基于这种诉求,在Jmeter中可使用if控制器来实现 二.实际操作 逻辑控制器位置: 在线 ...