[关闭]
@xiaoziyao 2021-05-01T14:19:52.000000Z 字数 1317 阅读 1021

P4594 [COCI2011-2012#5] BLOKOVI解题报告

解题报告


P4594 [COCI2011-2012#5] BLOKOVI解题报告:

更好的阅读体验

题意

从下到上有个矩形,重量分别为,以最下面矩形右下角为原点建立坐标系,那么定义一个矩形的重心为过其几何重心平行于轴的直线,一个矩形前缀的重心为直线

定义一种摆放方式合法当且仅当任意矩形的重心与其上方的矩形前缀的重心水平距离不超过,求出矩形右端点值最大值能取到的最大值。

分析

神仙题。

从下到上一个个考虑显然会产生后效性,因此从上到下讨论。

设现在到了第个矩形,之前的矩形(不包括)重量和为,之前的矩形的重心与当前矩形左端点的水平距离为(这是需要决策的值),前个矩形右端点与它们的重心距离最大值为

容易知道新的重心与左端点的距离为,前个矩形右端点与左端点的距离最大值为

因此可以知道前个矩形右端点与重心距离的最大值为

易知左边的是随增加单调减少的,右边的是随增加单调增加的,因此在允许的情况下,会尽可能取大或取小。

可以计算出矩形为底部时上一个的矩形的左端与当前矩形的左端水平距离最大值为,那么在右边放可以让当前的答案增加这个值。

如果放在右边,那么我们考虑两个矩形夹住当前矩形,那么至少要夹住长度的矩形才能保证平衡,那么当前右端为

这样贪心下去就好了,时间复杂度:

但是到这里其实我还是有一点疑惑,希望以后这道题的贪心有更好的解释。

代码

  1. #include<stdio.h>
  2. const int maxn=300005;
  3. int n;
  4. long long tot;
  5. double ans;
  6. int m[maxn];
  7. inline double max(double a,double b){
  8. return a>b? a:b;
  9. }
  10. int main(){
  11. scanf("%d",&n);
  12. for(int i=1;i<=n;i++)
  13. scanf("%d",&m[i]);
  14. for(int i=n;i>1;i--)
  15. ans=max(ans,max(ans+1.0*m[i]/(m[i]+tot),2.0-1.0*m[i]/(m[i]+tot))),tot+=m[i];
  16. printf("%.8lf\n",ans);
  17. return 0;
  18. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注