[NOI2004]降雨量

V.[NOI2004]降雨量

本题思路就和I.[HNOI2012]三角形覆盖问题差不多了。

首先,我们特判掉有长度为\(W\)的伞的情况——此时答案即为\(0\)

否则,对于每一时刻,我们计算出下面三种情况中,最先来到的一个:

  1. 有一把伞撞到了边缘

  2. 有两把伞,它们的某两个边缘相遇了(不管是哪两个边缘)

  3. 时刻\(T\)

然后就可以仍然使用梯形面积公式解决了(相遇的伞在空间中扫过的距离可以被看做梯形)。

因为题目保证所有伞的总往返次数不会超过\(250\),又此时每对不同的伞的每对往返都最多可以贡献一次相遇,故总相遇次数不会超过\(250^2\times 4=250000\)次(其中\(4\)是因为相遇时最多会有\(4\)个边缘相遇)。显然可以通过。

代码:

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-9;
int n,m,T,ita,ord[11];
double L[11],R[11],res;
int v[11];
double nex(){
	double minn=0x3f3f3f3f,tmp;
	for(int i=1;i<=n;i++){
		if(v[i]>0)minn=min(minn,(m-R[i])/v[i]);
		if(v[i]<0)minn=min(minn,L[i]/(-v[i]));
	}
//	printf("%lf\n",minn);
	for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){
		if(v[j]==v[i])continue;
		tmp=(R[j]-L[i])/(v[i]-v[j]);if(tmp>eps)minn=min(minn,tmp);
		tmp=(L[j]-L[i])/(v[i]-v[j]);if(tmp>eps)minn=min(minn,tmp);
		tmp=(L[j]-R[i])/(v[i]-v[j]);if(tmp>eps)minn=min(minn,tmp);
		tmp=(R[j]-R[i])/(v[i]-v[j]);if(tmp>eps)minn=min(minn,tmp);
	}
//	printf("%lf\n",minn);
	return minn;
}
void upd(double delta){
	for(int i=1;i<=n;i++)if(v[i])L[i]+=delta*v[i],R[i]+=delta*v[i];
	for(int i=1;i<=n;i++){
		if(!v[i])continue;
		if(fabs(L[i])<eps)v[i]=abs(v[i]);
		if(fabs(m-R[i])<eps)v[i]=-abs(v[i]);
	}
}
int qwq[11],tp;
double calc(){
	sort(ord+1,ord+n+1,[](int u,int v){return R[u]<R[v];});
	tp=0;
	for(int i=1;i<=n;i++){
		while(tp&&L[qwq[tp]]>L[ord[i]])tp--;
		qwq[++tp]=ord[i];
	}
	double ret=0;
//	for(int i=1;i<=tp;i++)printf("[%lf %lf]\n",L[qwq[i]],R[qwq[i]]);
	for(int i=1;i<=tp;i++)ret+=R[qwq[i]]-max(L[qwq[i]],R[qwq[i-1]]);
	return ret;
}
int main(){
	scanf("%d%d%d%d",&n,&m,&T,&ita);
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%d",&L[i],&R[i],&v[i]);
		if(R[i]==m){puts("0.00");return 0;}
		R[i]+=L[i],ord[i]=i;
	}
	upd(0);
	double tim=0,las=calc();
	while(fabs(T-tim)>eps){
		double delta=nex();
		delta=min(delta,T-tim);
		upd(delta);
//		for(int i=1;i<=n;i++)printf("[%lf %lf]\n",L[i],R[i]);
		double now=calc();
//		printf("(%lf %lf):%lf\n",now,las,delta);
		res+=(now+las)*delta/2;
		las=now;
		tim+=delta;
	}
	printf("%.2lf\n",(m*T-res)*ita);
	return 0;
} 

原文地址:https://www.cnblogs.com/Troverld/p/14619286.html