2022-10-07哇萌新第一次使用blog 感觉有点激动()
采药(背包题)一题应该是非常经典了,不过本人今天才接触到。讲一讲心路历程。


1、第一步拿到的时候,不管三七二十一,先做简单的定义数组,存入数据等等。然后考虑到一个比例的问题,即单位时间内能得到多少价值的药品。于是对各个数据进行了排序,再通过累加在判断小于最大时间的情况下输出。然后发现这样做根本不能避免很多问题,比如虽然拿了性价比最高的药,但是可能剩下的时间不够余下任何一个草药的采摘。于是卡住不知道怎么做了。
2、朋友告诉我这个优化是有关动态压缩的问题(昨天做了一道过河卒),但是我一下子没有联想到两者间有什么关系。
3、草草地看了一下题解作为hint,发现时间也可以遍历,从1-T遍历一遍,瞬间打开思路,于是自己又去写了。然后得到所示代码(含了我测试用的代码),然后输入输出,诶,这个不对,检查了一下

这个在我i=3进行状态转移的时候,反复叠加了,也就是说我这个优化是错误的,检查本来是的方程是s[i][t]=max(s[i-1][j-t[i]]+v[i],s[i-1][j]),这没错,“优化”错误的本质是在计算s[j-t[i]]的时候,v[i]可能已经加进去了
3.时间的遍历应该是思路正确的。如何解决,我想判断有无采过药了,如果采过了,那么在后续的s[j]全部赋予相同的值,于是快速写了一个(左图)

新的问题来了,这样会导致如果新的药所需时间很小,而上一种药时间很大,在T很大时候还是赋值了第i种,也就是完全一维了。
3.回到错误的地方,错误的原因是当时间j=t[i]足够采药之后,后续会覆盖本应该用于检查的上一组数据并且时间j>=2t[i]时会反复叠加。
思考,实际上,对于i的每一轮,最后是要在时间T的位置判断草药要不要采,即是我们要的最终结果,那么遍历的根本目的是什么呢,是更新状态,对于i的一轮中,每一个状态应该是独立的,即计算先后顺序在二维数组的情况下是没有关系的,遍历顺序无所谓。
而我们计算的时候是拿当前时间减去t[i],遍历时顺序是从前向后,那么当然是拿前面本轮的数据,换言之,如果从大到小就没关系了。于是我们做一个极小的改动
ohhhhhhhhh 一遍全ac!
反思:
状态压缩注意方向,注意需不需要叠加,我想或许这里有一个关键的思考的维度,即每轮数据的相关性,昨天的那道过河卒,需要叠加上一步走到那里的步数,所以从小到大遍历才能叠加,这次不能叠加,草药只采一遍,所以要从大到小,以后可能会有其他的相关方式,可以在此处做文章。
浙公网安备 33010602011771号