「SDOI2018」物理实验
题目大意:
这题不好描述,直接看原题吧……
题解:
很无脑的题……就是卡精度+难写。代码能力还是太差了。
其实可以直接用long double肝过去。但我的代码似乎太丑了,以至于跑得奇慢无比。
代码:
#include "bits/stdc++.h" using namespace std; inline int read() { int s=0,k=1;char ch=getchar(); while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); while (ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); return s*k; } #define double long double const double eps=1e-10; const int N=1e4+10; inline int dcmp(double a) { if (a>eps) return 1; if (a<-eps) return -1; return 0; } struct P{ P(double _x=0.0,double _y=0.0):x(_x),y(_y){} double x,y; double &operator [] (int k) {return k?y:x;} friend bool operator <(P a,P b) { return dcmp(a[0]-b[0])==-1||(dcmp(a[0]-b[0])==0&&dcmp(a[1]-b[1])==-1); } friend double operator *(P a,P b) { return a[0]*b[1]-b[0]*a[1]; } friend P operator /(P a,double b) { return P(a[0]/b,a[1]/b); } friend P operator + (P a,P b) { return P(a[0]+b[0],a[1]+b[1]); } friend P operator * (P a,double b) { return P(a[0]*b,a[1]*b); } friend double operator /(P a,P b) { return a[0]*b[0]+b[1]*a[1]; } inline double leth(){ return sqrt(x*x+y*y); } }; P operator -(P a,P b) { return P(a[0]-b[0],a[1]-b[1]); } struct L{ L(){}L(P _a,P _b):a(_a),b(_b),c(_b-_a),slope(atan2((a-b)[1],(a-b)[0])){} P a,b,c;double slope; P &operator[] (int k) { if(!k) return a; if (k==1) return b; return c; } friend double touying (L x,L y) { return x[2]/y[2]/(x[2].leth()); } friend double touying (L x,P y) { return x[2]/(y-x[0])/(x[2].leth()); } friend bool operator <(L x,L y) { double pos = max (x[0][0],y[0][0]); return dcmp(fabs(x[0][1] + x[2][1] * (pos-x[0][0]) / ( x[1][0] - x[0][0] )) - fabs(y[0][1] + y[2][1] * (pos-y[0][0]) / ( y[1][0] - y[0][0] )) ) == -1; } }block[N],gui; inline bool Judge(L a,L b) { return dcmp(b[2]*(a[0]-b[0]))==1; } inline double dis(P p,L l) { return l[2]*(p-l[0])/l[2].leth(); } double lft[N],lth[N],rght[N],rth[N]; int n,leth,m; int pl[N],pr[N]; struct node { P pos;int id; friend bool operator <(node a,node b) { return a.pos<b.pos; } }np[N*6]; set<L> up,down; double res[N*6]; inline double calc (double x2,double x1,L l) { P delta=l[2]*(x2-x1)/l[2][0]; return delta.leth(); } int main(){ int T=read(); register int i,j; while (T-- ) { n=read(); for (i=1;i<=n;++i) { double x1=read(),y1=read(),x2=read(),y2=read(); if (x1>x2) swap(x1,x2),swap(y1,y2); if (x1==x2&&y1>y2) swap(y1,y2); block[i]=L(P(x1,y1),P(x2,y2)); } double x1=read(),y1=read(),x2=read(),y2=read();leth=read(); if (x1>x2) swap(x1,x2),swap(y1,y2); if (x1==x2&&y1>y2) swap(y1,y2); gui=L(P(x1,y1),P(x2,y2)); m=0; for (i=1;i<=n;++i) { P a=block[i][0],b=block[i][1]; P na,nb; na[0] = touying(gui,a),na[1] = dis(a,gui); nb[0] = touying(gui,b),nb[1] = dis(b,gui); if (nb<na) swap(na,nb); block[i] = L(na,nb); np[++m] = (node){na,i} ; np[++m] = (node){nb,-i} ; np[++m] = (node){P (na[0]+leth,na[1]),0}; np[++m] = (node){P (nb[0]+leth,nb[1]),0}; np[++m] = (node){P (na[0]-leth,na[1]),0}; np[++m] = (node){P (nb[0]-leth,nb[1]),0}; } sort(np+1,np+m+1); up.clear(); down.clear(); double ans = 0.0,tmp,ret=0.0; j=1; while (j<=6*n) { if (np[j].id<0) { if (block[-np[j].id][0][1]<-eps) down.erase(block[-np[j].id]); else up.erase(block[-np[j].id]); }else if (np[j].id>0){ if (block[np[j].id][0][1]<-eps) down.insert(block[np[j].id]); else up.insert(block[np[j].id]); } ++j; res[j]=0.0; if (up.size()){ tmp = calc (np[j].pos[0],np[j-1].pos[0],*up.begin()); res[j] +=tmp; } if (down.size()) { tmp = calc (np[j].pos[0],np[j-1].pos[0],*down.begin()); res[j] +=tmp; } } for (i=j=1;i<=6*n&&j<=6*n;++i,ans-=res[i]) { while (j<=6*n&&dcmp(np[j].pos[0]-np[i].pos[0]-leth)<=0) ans+=res[j++]; ret=max(ret,ans); } printf("%.15Lf\n",ret); } }
没有什么不可能。