一些前言:

据说动态规划会用排序,数据结构来进行乱搞优化操作

动态规划滴核心是个啥呢?状态表示和状态转移

设状态:哪些因素会影响到最终答案,就把哪些因素用数组的维度表示出来

要充分描述,也要简洁

举个例子

计算从(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)的更多相关文章

  1. 【专章】dp基础

    知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. ----------------------------------------------------------- ...

  2. 【学习笔记】dp基础

    知识储备:dp入门. 好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了. dp基础,主要是做题,只有练习才能彻底掌握. 洛谷P1417 烹调方案 分析:由于时间的先后会对结果有影响,所以c[i ...

  3. hdu 2089 不要62 (数位dp基础题)

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. poj 2955 Brackets (区间dp基础题)

    We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...

  5. DP基础(线性DP)总结

    DP基础(线性DP)总结 前言:虽然确实有点基础......但凡事得脚踏实地地做,基础不牢,地动山摇,,,嗯! LIS(最长上升子序列) dp方程:dp[i]=max{dp[j]+1,a[j]< ...

  6. 树形dp基础

    今天来给大家讲一下数形dp基础 树形dp常与树上问题(lca.直径.重心)结合起来 而这里只讲最最基础的树上dp 1.选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程 ...

  7. poj2642 The Brick Stops Here(DP基础题)

    比基础的多一点东西的背包问题. 链接:POJ2642 大意:有N种砖,每种花费p[i],含铜量c[i],现需要用M种不同的砖融成含铜量在Cmin到Cmax之间(可等于)的砖,即这M种砖的含铜量平均值在 ...

  8. UVA103 dp基础题,DAG模型

    1.UVA103 嵌套n维空间 DAG模型记忆化搜索,或者 最长上升子序列. 2.dp[i]=max( dp[j]+1),(第i个小于第j个) (1) //DAG模型记忆化搜索 #include< ...

  9. 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 ...

随机推荐

  1. IntelliJ IDLE

    目录 IntelliJ IDLE java项目结构 代码生成 psvm sout 快捷键 更改代码提示快捷键 代码相关快捷键 窗口相关快捷键 Debug快捷键 主题导入 下载主题 导入主题 应用主题 ...

  2. uboot启动第一阶段分析

    一. uboot第一阶段初识 1.1. 什么是uboot第一阶段 1.1.1. 启动os三个阶段 1.1.1.1. bl0阶段 a. 这段代码是三星固化到iROM中,可以查看<S5PV210_i ...

  3. Linux——临界段,信号量,互斥锁,自旋锁,原子操作

    一. linux为什么需要临界段,信号量,互斥锁,自旋锁,原子操作? 1.1. linux内核后期版本是支持多核CPU以及抢占式调度.这里就存在一个并发,竞争状态(简称竟态). 1.2. 竞态条件 发 ...

  4. Period II

    For each prefix with length P of a given string S,if S[i]=S[i+P] for i in [0..SIZE(S)-p-1], then the ...

  5. idea使用Vue的v-bind,v-on报错

    参考解决在WebStorm中使用Vue的v-bind,v-on报错 File-->Settings-->Editor-->Inspections-->XML 把 Unbound ...

  6. O-超大型LED显示屏

    Input 输入包含不超过100组数据.每组数据第一行为”START hh:mm:ss”,表示比赛开始时刻为hh:mm:ss.最后一行为”END hh:mm:ss”,即比赛结束时刻.二者之间至少会有一 ...

  7. 求大组合数mod p,(p不一定为质数)

    #include<bits/stdc++.h> using namespace std; typedef long long ll; #define N 2000005 ll p; ll ...

  8. vue实现动画和css3动画属性

    一.vue动画实现原理: 动画的实现,必须通过元素的显示隐藏或销毁创建.v-show  v-if vue中如果需要使用动画的时候,需要使用一个内置组件transition组件 该组件有一个name属性 ...

  9. C# wpf 列出文件夹所有文件

    在网上找了 cmd输入 dir "要列出的文件夹*.*" /a /b /s>"要输出的文件" 可以重定向把文件夹内容输出到文件 tree "要列 ...

  10. Educational Codeforces Round 32 Almost Identity Permutations CodeForces - 888D (组合数学)

    A permutation p of size n is an array such that every integer from 1 to n occurs exactly once in thi ...