[JZOJ3171] 【GDOI2013模拟4】重心

题目

描述

在这里插入图片描述

题目大意

有一堆长为 2 2 2的矩形,最下面的右端点横坐标为 0 0 0
每个矩形都有其固定的质量。
将这些矩形堆在一起,使得最右边的横坐标最大,并且满足它不会塌掉(满足物理学)。


思考历程

首先就觉得这是一道结论题。
这个东西看起来不可以DP做,所以就往贪心的方面想。
我想从上往下推过来,计算出可能的最左和最右的重心的位置。
在计算的时候记录一下最右边的点。
实际上我的这个想法存在着太多的漏洞,以至于我连样例也没有过。


正解

首先,最优的方案一定是长成“ > > >”形状的。
接下来我们枚举这个凸出来的矩形,设其为 x x x
x x x下面的尽量往右伸,在 x x x上面的往左伸。右伸是为了使得答案尽量大,左伸是为了让答案尽量大的时候可以保持平衡。
现在我们需要让 x x x以及它上面的矩形可以立足于 x − 1 x-1 x1的矩形上。
由于 x x x要尽量往右,那我们就钦定这一大块的重心在 r x − 1 r_{x-1} rx1处( r i r_i ri表示 i i i矩形的右边横坐标)
又由于 x x x上面的矩形要往左,所以我们就钦定它们的重心在 r x − 2 r_x-2 rx2上(一定有满足这种条件的方案)。
M M M x x x上面的矩形的质量和, m x m_x mx x x x的质量,依照公式:
r x − 1 = M ( r x − 2 ) + m x ( r x − 1 ) M + m x r_{x-1}=\frac{M(r_x-2)+m_x(r_x-1)}{M+m_x} rx1=M+mxM(rx2)+mx(rx1)
如果我们知道 r x − 1 r_{x-1} rx1,就可以解出 r x r_x rx,然后统计入答案。
那这个 r x − 1 r_{x-1} rx1是怎么来的呢?
显然不可以有上一次 i = x − 1 i=x-1 i=x1时解出来的结果,具体原因不在赘述。
转化成另一个问题,现在 x x x不是最右边的矩形,最右边的矩形会出现在它的上方。
所以 x x x上面的矩形要尽量往右伸,我们可以将它们的重心钦定为 r x r_x rx,然后方程就出来了。
r x − 1 = M r x + m ( r x − 1 ) M + m z r_{x-1}=\frac{Mr_x+m(r_x-1)}{M+m_z} rx1=M+mzMrx+m(rx1)
同样可以通过 r x − 1 r_{x-1} rx1解出 r x r_x rx,解出之后用来更新现在的 r x − 1 r_{x-1} rx1,计算下一个答案。
时间显然是线性的。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300010
int n;
int w[N];
int main(){
	scanf("%d",&n);
	double sum=0;
	for (int i=1;i<=n;++i)
		scanf("%d",&w[i]),sum+=w[i];
	sum-=w[1];
	double r=0,ans=0;
	for (int i=2;i<=n;++i){
		sum-=w[i];
		ans=max(r+1+sum/(sum+w[i]),ans);
		r=r+w[i]/(sum+w[i]);
	}
	printf("%.8lf\n",ans);
	return 0;
}

总结

在贪心的时候,有时可以“钦定”一下,假设除最好的情况来计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值