zoukankan      html  css  js  c++  java
  • [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;
    } 
    

  • 相关阅读:
    面向对象简述
    python面向对象
    Python中int()函数的用法浅析
    给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
    python中关于round函数的小坑
    Xmind8破解,以及相关的流程和破解包
    生成器和生成器表达式
    brush图标
    js声明全局变量的方式
    js修改全局变量
  • 原文地址:https://www.cnblogs.com/Troverld/p/14619286.html
Copyright © 2011-2022 走看看