动态规划网课小结
由于弹出顺序的不同会导致工作序列的不同,所以我们要求最优的工作序列。
状态定义:\(f[l][r]\) 表示产品编号在 \(l\) ~ \(r\) 这个区间的产品所带来的最小惩罚值是多少。
先决定这个区间的产品在工作序列中最靠后的是多少:假设最后一个是 \(k\),那么 \(1\) 到 \(k-1\) 肯定在 \(k\) 入栈前弹出,\(k+1\) 到 \(n\) 在 \(k\) 入栈后弹出。
也就是工作序列中 \(1\) 到 \(k-1\) 均在 \(k+1\) 到 \(n\) 前面。
那么只需要枚举 \(k\),就可以把问题分为互不交叉的两个部分。
做法显然:区间 \(dp\)。
我们先预处理 \(S[i]\) 表示 \([1,i]\) 这段区间的时间是多少。
转移方程:\(f[l][r]=min(f[l][r],f[l][k-1]+f[k+1][r]+\sum_{i=l}^{k-1}t_i*\sum_{i=k+1}^{r}d_i+\sum_{i=l}^{r}*d_k)\)
\(dp[i][0]\) 表示以 \(i\) 为根的子树中选取任意多无不相邻的点的最大权值,且 \(i\) 点本身不选的最大权值。
\(dp[i][1]\) 表示以 \(i\) 为根的子树中选取任意多无不相邻的点的最大权值。
则 \(dp[i][0]=\sum_{k}*dp[k][1]\),其中 \(k\) 为 \(i\) 的儿子。
及 \(dp[i][1]=max(dp[i][0],\sum_{k}dp[k][0]+v[i])\),其中 \(k\) 为 \(i\) 的儿子。
假设根节点为 \(x\),则答案为 \(dp[x][1]\)。
状态定义:\(dp[i][j][k]\) 表示走到格子 \((i,j)\),背包容量还剩 \(k\) 时获得的最大价值。
\(dp[i][j][k]=max(dp[i-1][j][k],dp[i][j-1][k],dp[i-1][j][k+v_{i,j}]+W_{i,j},dp[i][j-1][k+v_{i,j}]+W_{i,j})\)
\(k+v_{i,j}>S\) 时去掉后面两项。
时间复杂度 \(O(n^2S)\)。
可以注意到选课的结构构成了一个森林。(如果令没有先修课的点的父亲为 \(0\),则为一棵树)。
令 \(dp[i][j]\) 表示在以 \(i\) 为根的子树中选择了 \(j\) 门课程学习,所能得到的最大学分(\(i\) 自身必须选择)。
对于每一个点,用气各儿子的信息依次更新。
对于每一个儿子 \(x\),枚举所选课程 \(k\),则更新方式为:
\(dp[i][j+k]=max(dp[i][j+k],dp[i][j]+dp[x][k]\)。注意为了防止重复更新(即同一个儿子被选了多次的情况),最好用一个辅助数组缓存更新后的值,在这个儿子处理完毕后再将辅助数组的值覆盖进 \(dp\) 数组。
每一个节点会向上更新一次,每一次更新要枚举子节点和父节点的第二维,所以总复杂度为 \(O(nm^2)\)。
对于题目要求的 \([a,b]\) 中每个数码的个数,我们可以转化为 \([1,b]\) 的答案减去 \([1,a-1]\) 的答案。那么我们只需实现一个函数 \(get(x)\),使其求得 \([1,x]\) 的答案。
定义 \(f[i][j][k]\) 表示以 \(j\) 开头的 \(i+1\) 位数中数码为 \(k\) 的个数。(这里允许有前导零)
那么可以得到方程 \(f[i][j][k]=\sum){p=0}^{9}f[i-1][p][k]+[j==k]*10^i\)
令 \(x\) 的总位数为 \(t\),那么位数小于 \(t\) 的数全部可以贡献答案;
位数等于 \(t\) 的,如果最高位小于 \(x\) 的最高位,也可以直接贡献答案;
如果最高位等于 \(x\) 的最高位,则得到当前最高位产生的贡献,去掉最高位继续处理。
令 \(f[i][S]\) 表示当前在第 \(i\) 关,之前所吃过的宝物集合为 \(S\),可以获得的分值得期望值。
\(f[i][S]=\frac{1}{n}\sum_{j=1}^{n}max(f[i+1][S],[(S\)&\(s_j)==s_j](f[i+1][S|2^{j-1}]+P_j))\)