线性DP
带你深入浅出线性DP
矩阵不需要秩
这个作者很懒,什么都没留下…
展开
-
01背包问题
如果选,那么f[i][j]=f[i-1][j-v[i]]+w[i],这里的意思是如果你选了第i个物品,那么它所获得的最大价值就相当于你在前i-1个物品中选,体积变为j-v[i]所获得的最大价值加上你选择第i个物品的价值w[i]。那么如果你没选呢,就相当于你从前i-1个物品中选,背包体积为j的所获得的最大价值。从AC代码中我们可以注意到,f[i][j]只会和f[i-1][]相关,也就是第i层只会和第i-1层相关,前面的i-2层是无关的,所以我们没有必要开f[N][N],只需要开f[2][n]就可以了。原创 2023-09-04 20:29:16 · 35 阅读 · 1 评论 -
完全背包问题
这里的话,可以用滚动数组优化,读者可以自己优化。和01背包差不多,状态的转移就有略微的差别,也就是选了第i个物品之后不是从前i-1个物品中选了,而是还是从前i个物品中选,还是很好理解的。原创 2023-09-04 20:35:16 · 38 阅读 · 1 评论 -
多重背包问题
为什么呢,因为2000*1000*2000>1e8,所以就会tle。那么就要按照AC代码进行二进制优化,优化完就是2000*log(2000)*1000=2000*1000*11<1e8。显然时间符合了,再进行滚动数组优化,就可以AC了。不进行滚动的话,12010*2000*4>64000000。这里我们的物品的数量是2000*1000,那么空间复杂度2000*1000*2000*4显然大于64000000。但是这里我们不能把一个物品有多少份,而去给它分成多少份,这样的话,会mle。原创 2023-09-04 21:49:13 · 32 阅读 · 1 评论 -
分组背包问题
这里和01背包问题有点不同,就是一个组里面最多只能选一个物品。f[i][j]表示前i组物品背包体积为j所能获得的最大价值。那么这里的状态转移,首先可以第i组物品一个都不选,也就是f[i-1][j]。然后就是第i组物品中选一个,和01背包问题一样,取一个max就可以了。也可以进行滚动数组进行优化。原创 2023-09-05 20:58:43 · 35 阅读 · 1 评论 -
最长上升子序列
我么可以使用STL的lower_bound函数在f数组里面找到第一个大于或等于它的位置,因为它是大于或等于当前遍历到的这个数,所以我们就要去替换它,因为f数组的定义是长度为i的上升序列的一个最小的结尾,我们用lower_bound找到这个位置,因为这个数一定加在比他小并且是最长的一个序列的后面,注意一定是最长的一个序列,那么我么这里的f数组刚刚证明了是严格单调递增的。因为这里的f[6]是根据f[5]来的,有一点动态规划的思想,所以它的一个最小结尾是根据大于长度是5的一个最小结尾的所有数的一个最小值。原创 2023-09-05 23:56:43 · 35 阅读 · 1 评论 -
最短编辑距离
特别注意一下,这里首先要初始化一下最开始的边界情况,因为这里从1开始遍历,那么f[0][3]如果不特别初始化一下的话,就是0,那么显然是错误的,所以提前初始化一下。如果要在第i个位置后面增加一个元素可以和b的匹配的话,那么f[i][j]=f[i][j-1]+1。这里有两种情况,第一种情况a[i]==b[j],那么f[i][j]=f[i-1][j-1]。第二种情况,a[i]!=b[j],那么f[i][j]=f[i-1][j-1]+1。如果要删除第i个位置的元素的话,f[i][j]=f[i-1][j]+1。原创 2023-09-29 20:23:12 · 184 阅读 · 0 评论