sairate c9f8710d03 sairate<sairate@sina.cn>
Signed-off-by: sairate <sairate@sina.cn>
2025-07-12 16:05:52 +08:00

227 lines
5.4 KiB
C++

//*************************************
//* *
//* NOI 2004 *
//* Day ? Problem ? *
//* rainfall.cpp *
//* by Wu Jingyue *
//* *
//*************************************
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <iomanip>
using namespace std;
struct TBoard
{
double x,l,v;
};
struct TSegment
{
double x1,y1,x2,y2;
int uorl,order;
};
struct TInterval
{
double x,y;
};
const int maxn=10;
const int maxm=500;
const int maxk=250000;
const double Zero=1e-6;
ifstream fin("rainfall.in");
ofstream fout("rainfall.out");
TBoard Board[maxn]; int n;
TSegment Segment[maxm]; int m;
double Time[maxk]; int k;
TInterval Interval[maxm]; int r;
double w,t,v,ans;
void Input_Data()
{
int i;
fin>>n>>w>>t>>v;
for (i=0; i<n; i++) fin>>Board[i].x>>Board[i].l>>Board[i].v;
fin.close();
}
double Multi(double x1,double y1,double x2,double y2)
{
return x1*y2-x2*y1;
}
double MAX(double a,double b)
{
if (a>b) return a; else return b;
}
double MIN(double a,double b)
{
if (a<b) return a; else return b;
}
bool Intersect(TSegment a,TSegment b)
{
if (MAX(a.x1,a.x2)<MIN(b.x1,b.x2)-Zero || MAX(b.x1,b.x2)<MIN(a.x1,a.x2)-Zero ||
MAX(a.y1,a.y2)<MIN(b.y1,b.y2)-Zero || MAX(b.y1,b.y2)<MIN(a.y1,a.y2)-Zero) return false;
return Multi(b.x1-a.x1,b.y1-a.y1,a.x2-a.x1,a.y2-a.y1)*Multi(b.x2-a.x1,b.y2-a.y1,a.x2-a.x1,a.y2-a.y1)<=Zero
&& Multi(a.x1-b.x1,a.y1-b.y1,b.x2-b.x1,b.y2-b.y1)*Multi(a.x2-b.x1,a.y2-b.y1,b.x2-b.x1,b.y2-b.y1)<=Zero;
}
double GetIntersection(TSegment s1,TSegment s2)
{
double a1,b1,c1,a2,b2,c2;
a1=s1.y1-s1.y2; b1=s1.x2-s1.x1; c1=s1.x1*s1.y2-s1.x2*s1.y1;
a2=s2.y1-s2.y2; b2=s2.x2-s2.x1; c2=s2.x1*s2.y2-s2.x2*s2.y1;
return (b1*c2-b2*c1)/(a1*b2-a2*b1);
}
int CompareDouble(const void *a,const void *b)
{
if (*(double *)a<*(double *)b) return -1;
else if (*(double *)a==*(double *)b) return 0;
else return 1;
}
int CompareInterval(const void *a,const void *b)
{
if (((TInterval *)a)->x<((TInterval *)b)->x) return -1;
else if (((TInterval *)a)->x==((TInterval *)b)->x) return 0;
else return 1;
}
double GetLen(double x)
{
double ans,max;
int i,j;
r=0;
for (i=0; i<m; i++)
if (Segment[i].uorl==0 && Segment[i].x1<=x+Zero && x<=Segment[i].x2+Zero)
{
Interval[r].x=((Segment[i].y1-Segment[i].y2)*x+Segment[i].x1*Segment[i].y2-Segment[i].x2*Segment[i].y1)/(Segment[i].x1-Segment[i].x2);
Interval[r].y=Interval[r].x+Board[Segment[i].order].l;
r++;
}
qsort(Interval,r,sizeof(TInterval),CompareInterval);
ans=0;
i=0;
while (i<r)
{
max=Interval[i].y;
j=i+1;
while (j<r && Interval[j].x<=max+Zero)
{
if (Interval[j].y>max) max=Interval[j].y;
j++;
}
ans+=(max-Interval[i].x);
i=j;
}
return ans;
}
void Solve()
{
int i,j;
double curx,curv,curt,it,l,l1;
m=0;
for (i=0; i<n; i++)
{
curx=Board[i].x; curv=Board[i].v; curt=0;
if (Board[i].l==w) curv=0;
if (curv==0)
{
Segment[m].x1=0; Segment[m].x2=t; Segment[m].y1=curx; Segment[m].y2=curx;
Segment[m].order=i; Segment[m].uorl=0; m++;
Segment[m].x1=0; Segment[m].x2=t; Segment[m].y1=curx+Board[i].l; Segment[m].y2=curx+Board[i].l;
Segment[m].order=i; Segment[m].uorl=1; m++;
continue;
}
while (curt<t)
{
Segment[m].x1=curt; Segment[m].y1=curx;
if (curv>0)
{
curt+=(w-Board[i].l-curx)/fabs(curv);
curx=w-Board[i].l;
}
else
{
curt+=curx/fabs(curv);
curx=0;
}
Segment[m].x2=curt; Segment[m].y2=curx;
Segment[m].uorl=0; Segment[m].order=i;
if (Segment[m].x1<Segment[m].x2-Zero)
{
m++;
Segment[m].x1=Segment[m-1].x1; Segment[m].y1=Segment[m-1].y1+Board[i].l;
Segment[m].x2=Segment[m-1].x2; Segment[m].y2=Segment[m-1].y2+Board[i].l;
Segment[m].uorl=1; Segment[m].order=i;
m++;
}
curv=-curv;
}
}
// fout<<"NSegment="<<m<<endl;
/*
for (i=0; i<m; i++)
{
Time[k]=Segment[i].x1; k++;
Time[k]=Segment[i].x2; k++;
}
*/
k=0;
Time[k]=0; k++;
for (i=0; i<m; i++)
for (j=i+1; j<m; j++)
if (Intersect(Segment[i],Segment[j]))
{
it=GetIntersection(Segment[i],Segment[j]);
if (it>Zero && it<t-Zero)
{
Time[k]=it;
k++;
}
}
Time[k]=t; k++;
// fout<<"NTime="<<k<<endl;
qsort(Time,k,sizeof(double),CompareDouble);
j=0;
for (i=0; i<k; i++)
if (i==k-1 || Time[i]<Time[i+1]-Zero)
{
Time[j]=Time[i];
j++;
}
k=j;
ans=v*w*t;
l=GetLen(Time[0]);
for (i=0; i<k-1; i++)
{
l1=GetLen(Time[i+1]);
ans-=v*(l+l1)/2*(Time[i+1]-Time[i]);
l=l1;
}
}
void Output_Data()
{
fout<<setiosflags(ios::fixed)<<setprecision(2)<<ans+Zero<<endl;
fout.close();
}
int main()
{
Input_Data();
Solve();
Output_Data();
return 0;
}