那么简单来说就是现在的决策内容会对之后的计算价值产生影响
那么我们怎么办:简单,如果这个影响是我们能够求的,那么我们就当前计算就好了!
1. 先把所有的点包括起点按 x 值排序,这样题目就变成从起点出发,每次可以 向左或向右走到最近的某个彩蛋,将其射落,
设每个彩蛋第一次走到的时刻为ti,答案就是∑max (yi - ti * vi)
2 很容易想到用 f[1][i][j]f[1][i][j]、f[2][i][j]f[2][i][j]分别表示从起点出发已射落 i 到 j 这一段彩蛋,当前停留在 i 点、j 点的最大得分.
考虑 f[1][i][j]f[1][i][j],即点 i 是当前射击的彩蛋,射击的得分与当前时刻挂钩,但 是当前的时刻是不能从 f[1][i][j]f[1][i][j]的状态中表示出来的。
我们发现上述方法的矛盾其实就在于曾经的行走花费的时间会对当前的得分产生影响, 我们可以进一步考虑 f[1][i][j]f[1][i][j]的求解,由于射击 i 的得分是 yi-t*viyi−t∗vi,
而 t 等于之前每一步决策移动的时间总和,这样我们就可以把t*v_it∗vi?在之前的移动中就计算,也就是说每次移动都要把未来会减少的得分计算在内。
比如说从 f[1][i][j]f[1][i][j]推到 f[1][i-1][j]f[1][i−1][j],即从 i 走到 i-1 时除了 i 到 j 这一段彩蛋 外,其它的彩蛋都在下落,将这丢失的分数一并计算到从 i 走到 i-1 中。
由于-t*vi 已经在之前决策时计算,所以射击时加上 yi 即可。
3 接着,让我们模拟走的过程(就是dp方程)。
如果我们要走i到j这段连续的小球(注意 i、j不是起点与终点,是范围),我们有许多走法,但总结起来,就是由两种走法组成
- 从i走到j(反向同理)
- 从i走到j,并且从j回到i(反向同理)
所有的走法,均由这两种重复形成。
如果考虑更细,我们发现
- 从i走一步,到j;
- 从i返回,到之前的一点
f[i][j] :走完i到j,在i处
g[i][j] :走完i到j,在j处
试想:f[i][j]怎么来的? 你可能会说:i到j的走法那么多,得到的方法太多了。回想刚刚说的,就两种
- 上一步为f[i-1][j], 往左边走一步,得到f[i][j]。
- 上一步为g[i-1][j],往左跨过这段区间,走到i 得到f[i][j];
f[i][j]=min(f[i][j],f[i+1][j]+(js(1,i)+js(j+1,n))*(ball[i+1].x-ball[i].x)); f[i][j]=min(f[i][j],g[i+1][j]+(js(1,i)+js(j+1,n))*(ball[j].x-ball[i].x));
g[i][j]=min(g[i][j],g[i][j-1]+(js(1,i-1)+js(j,n))*(ball[j].x-ball[j-1].x)); g[i][j]=min(g[i][j],f[i][j-1]+(js(1,i-1)+js(j,n))*(ball[j].x-ball[i].x));
代码中js(a,b) 函数指a到b这一段小球的下落速度之和(事先用前缀和维护) 乘上移动距离的位置差(就是时间差),得到f[i][j]这一段丧失的得分
问题得以解决。
原文地址:https://www.cnblogs.com/gjc-blog/p/11470112.html