P2672 推销员 优先队列 + 贪心

匿名 (未验证) 提交于 2019-12-03 00:41:02

~~~题面~~~

题解:

我会说我想这道普及组题都想了好久么。。。。

不熟练的普及组选手.jpg

最后随便猜了一个结论居然是对的。。。

放结论:

假设x = i的最优决策为f[i], 那么f[i + 1]一定包括f[i].

也就是说f[i+1]一定可以由f[i]推出来。

所以f[i]一定是由f[i+1]中选定的所有点中去掉一个得来的。

即下一次选择一定是基于上一次选择的。。。

至于证明嘛。。。感性理解吧。

因为选哪户人家推销其实相互没太多联系。而且选i个推销肯定选满是最划得来的。。。。

大概是这么理解的吧。(反向理解可能更加好理解一点)

所以有了这个结论就很好解决了。

因为f[n]的最优决策肯定是n个点全选。

所以我们从这个已知的往前推。

于是我们来观察这n个点,到底删掉哪个减掉的疲劳值最小呢?

首先选中的这些点可以看做一个有序点集,位置由s[i]的大小所决定。

因此我们记last[x]为在x前面的第一个点的id, Next[x]为在x后面的第一个点的id。

于是有两种情况:

1,删去的点在末尾。

  此时减掉的疲劳值为a[x] + 2 * (s[x] - s[last[x]])

2,删去的点在中间。

  那么此时对走路的距离没有任何影响,因此我们只需要减a[x]即可。

值得注意的是,当末尾点k为a[i]最小的点时, 我们需要再取出次小的点来做比较,因为a[k]虽然最小,但由于要走很多路,所以a[k] + 2 * (s[k] - s[last[k]])并不一定小于a[i](i < k, 且i ∈ 点集),因此我们需要进一步比较再做取舍。

而k不是a[i]最小的点时,因为a[k]就已经大于a[i]了,所以减去的疲劳值肯定要大于a[i]了,因此直接删最小的点就可以了。

这里的最小和次小由于要支持插入,删除,查询,因此我们使用优先队列来实现。

为了方便查询元素的id,,,于是我又建了一个结构体、。

代码:

原文:https://www.cnblogs.com/ww3113306/p/9315731.html

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!