hdu5303贪心
http://acm.hdu.edu.cn/showproblem.php?pid=5303
说一下题目大意。。
有一个长为L的环。。你家在原点位置0,那么剩下L-1个点上种有一些树,
给你树的位置和每颗树上有多少颗苹果。。然后你有一个大小为k的篮子
摘完苹果拿回家去。。然后再拿。。问你总路程最小是多少。。
上面是一个额外的限制。。但是我没把他当回事
读题有一个trick..那就是我看到了x[i]可以等于L
然后如果说原点是0.。那么长度为L的环。。还剩下1~L-1可以编号。。哪里来的L号呢。。
如果你强行放一个L号的进来。。那环的长度就变成了L+1不符合题意
但是我们怎么理解呢。。在环长度不变的情况下。。顺时针编号。。那么L号与0号重合。。我们只能这么理解了。。
这是读题的一点trick
把环切成两半,把树按距离排序
应该有两种策略。。第一从小的往大了取。。具体来说先取完小的。。取完小的篮子还有剩余怎么办,现在还不知道
第二从大往小了取。。具体来说。。先取完最大的。。然后再取次大的。。,但是有坑。。
我的第一个疑问是如果一趟搬运采用策略1直到单侧装满篮子(能装满的话),和策略2哪个更好。。
假如1位置是a,2位置是b
k>a,b>a,那么a取完之后篮子还有剩余要不要去把b的取了呢
如果取的话,总距离是
2*(2+2*floor((b-(k-a)+(k-1))/k*2))
不取的话总距离是
2*(1+floor((b+(k-1))/k*2))
(加上(k-1)是一个trick..余数不等于零那么就会给答案贡献1,[(1+(k-1))]/k=1,因为除数正好是k)
两者作个差。。但是带有floor函数的式子无法直接相减。。
因为floor(a)-floor(b)!=floor(a-b)比如说a=7.5,b=1.6,6!=floor(5.9)=5
但是带入公式我们就能发现。。k>a并且b>a时。。k越大。。好像没看出来关系。。233
但是我们发现。。有时不取B比取B更优。。
1,2 然后k=2,从前往后贪着取。。你会发现。。还不如取完第一个直接回家。。然后再取第二个(2+4)>(4+4)
我觉得原因主要在于多出来的容量没有把b全部带走
看了一下老顽童菊苣的题解明白了一些
http://taosama.github.io/2016/03/18/HDU%205303%20Delicious%20Apples%EF%BC%88%E8%B4%AA%E5%BF%83%EF%BC%89/
然后。。
貌似是这样的把苹果离散化之后,l[i]表示左侧取第i个苹果的最小代价。。将l数组排序以后
l[i]=pos[i]+l[i-k];翻译一下就是取第i个苹果的代价是第i个苹果到原点的距离加上取第i-k个苹果的代价
为什么这么搞是对的呢。。
现在窝好像终于懂了。。首先我们先分析了这个类似dp的东西递推。。前提要按从小到大排序。。
为什么要排序呢。。因为我们要从小到大贪。。至于之前的那个贪法。。确实不是固定的。。而且
先取完最小的。。再取完次小的这个策略并不是最优的。。
请注意我们如果以树为单位。。则需要去试。。每一次取多少苹果回去。。有时候空着篮子回去给后面留一个大包圆是最优的
并不是每一次取满最优。。
比如说6,2,3这个单侧的情况。。k=5,我们只是发现了顺着挨个取完最小的是2+6+6..
而直接取完小的篮子还有空余也不往前走。。直接回家的话是,2+2+6
并且。。先取后两个2,3再取6也是6+2+2=10
但是实际上正解用的是一种dp的策略。。因为它认为当前取第i个苹果的代价能够让篮子一次至少装够k是最优的。。
所以按照题目的推法6+2+3=11,l[11]=3+l[6],l[6]=1+l[1],l[1]=1+l[0],l[0]=0,l[0]是边界
所以。。实际上这个意思是说最终的方案是先l[1],再l[6],再l[11],就是第一次取一个。。第二次取k=5个取到6,第三次取k=5个到11
所以说即使从前往后面取。。全取也不一定是最优的呀。。这个一开始就没发现。。数据太难造了吧。。我擦
我们一开始就应该考察取法所造成的差别。。如果发现这是一个动态的取法的话。。就会往这方面想了。。这个东西简直玄学。。情况会变的。
也就是说增加苹果的数量对答案产生后效性。。但不改变之前的答案。。好吧说后效性不太好。。
由于我们是先算完左边再算了右边。。我们知道最后两边剩余等于k或者小于k我们可以一次绕圈解决。。
但是。。左边的剩余a,右边的剩余b,a+b<=k,有很多种情况。。那么我们枚举左边的剩下的就是右边的
因为我们离散化了。。所以这个就很好枚举了。。对应的离散情况的答案都算出来了。。
离散化真是tmd神了。。
这里的问题就是为什么我们不枚举那些小于k的的组合。。
前面已经枚举过了不绕圈的情况
后面我们要做的就是枚举一定绕一圈的情况。。事实上最优的话只能绕一圈。。详见老顽童博客。。上面的链接。。
我们观察到随着苹果数量的增多。。其代价一定是非严格单调增长
于是。。我们一定要绕一圈加上两边的剩余的苹果的代价。。那么我们一定是让两边剩余苹果越少越好。。
即让绕圈采摘的苹果越接近k越好。。即L一定l[a]+r[b]越小越好。。它越小则已经采摘的苹果数量就越少
所以我们只需要枚举k,而不需要枚举小于k的那些组合。。
对于k的所有组合。。比如说5,:1,2,3,4,*(4,3,2,1)=4种分成两半的组合
如果是3,4的话。。某个枚举可能会使3成为负数。。此时给它当成0看待
然后我们绕一圈仍然可以解决这个问题。。绕一圈一定能把这个<k的给弄走。。
然后这个题基本上做完了。。但是离散化和数据的构造都没有想到。。这是非常致命的一点
========
对于前面那个采摘满篮子的猜想。。
如果我们从后面往前贪心的话
取完1我们是往回削2呢还是往前削1呢。。
经过简单计算。。显然削1答案更小。。
对于这个我们先取了最远的1,如果往后。。+6
然后+4,+2,+6
如果我们先取1,往回走,+6,+2,再取右边的2,+6
显然比上面好。。
于是我们先取最后一个就不好判断你是往回走还是往前走了。。
而且如何能判断最优呢。。你必须全算出来才行。。才能比较大小。。
即使你这次不绕圈。。下次可能就会满足绕圈的契机了。。
但是只绕一圈好像没法证明。。
你这样的话。。真的不好算啊。。
枚举每次绕不绕。。就变成搜索了。。而且好像不太能搜啊。。