由于弹出顺序的不同会导致工作序列的不同,所以我们要求最优的工作序列。
状态定义:(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)))