记录编号 381135 评测结果 AA
题目名称 [NWERC2007]飞行安全 最终得分 100
用户昵称 GravatarsssSSSay 是否通过 通过
代码语言 C++ 运行时间 1.560 s
提交时间 2017-03-10 21:38:20 内存使用 4.12 MiB
显示代码纯文本
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>

#define INF 1000000005
#define eps 1e-6
#define Make make_pair

using namespace std;

typedef pair<double,double> P;

struct node {double v[3],u[3],k,b;}e[30010];
struct nodc {double x[40],y[40];}G[40];
struct noda {double v[3],u[3],k,b;}Ge[30010];

int T,n,c,tot,cnt,m,l[40],r[40];P L;
int Q[30100];
double Res = 0.0;

bool Comp(double q,double w){
	if(fabs(q - w) <= 1e-6)return 1;
	else return 0;	
}

P CalLen(int k,double l){return Make((e[k].u[0] + l * L.first),(e[k].u[1] + l * L.second));}

P GetMid(int k){return Make((e[k].u[0] + e[k].v[0]) / 2,(e[k].u[1] + e[k].v[1]) / 2);}

P CalMag(int k){return Make((e[k].v[0] - e[k].u[0]),(e[k].v[1] - e[k].u[1]));}

double Dis(P a,P b){
	double x1 = a.first,x2 = b.first,y1 = a.second,y2 = b.second;
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
bool OnLine(int x,P aa,int p){double x0 = aa.first,y0 = aa.second;
	double xx1 = p == 1 ? Ge[x].u[0] : e[x].u[0],xx2 = p == 1 ? Ge[x].v[0] : e[x].v[0];
	double yy1 = p == 1 ? Ge[x].u[1] : e[x].u[1],yy2 = p == 1 ? Ge[x].v[1] : e[x].v[1];
	if(yy1 > yy2){swap(yy1,yy2);swap(xx1,xx2);}
	if(xx1 == xx2 && y0 >= yy1 && y0 <= yy2 && x0 == xx1)return 1;
	double k1 = p == 1 ? Ge[x].k : e[x].k,b1 = p == 1 ? Ge[x].b : e[x].b;
	if(fabs(k1 * x0 + b1 - y0) > eps)return 0;
	if(k1 >= 0 && x0 >= xx1 && x0 <= xx2 && y0 >= yy1 && y0 <= yy2)return 1;
	if(k1 < 0 && x0 >= xx2 && x0 <= xx1 && y0 >= yy1 && y0 <= yy2)return 1;
	return 0;
}

P CalInt(int k,P a){//This Is A Mistake!!! Update : 2017/3/7 11:38 About...This is Right
	//Update:2017/3/10 20:04 Oh...Why Did Not Me Judge If Point On Line???(╯‵□′)╯︵┻━┻ 
	//Update:2017/3/10 20:08 Oh Yeah It is Really Right
	double x1 = Ge[k].u[0],y1 = Ge[k].u[1],x2 = Ge[k].v[0],y2 = Ge[k].v[1];
	double x0 = a.first , y0 = a.second;
	if(Comp(x1,x2)){
		if(y0 >= y1 && y0 <= y2)return Make(x1,y0);
		else return (Dis(a,Make(x1,y1)) <= Dis(a,Make(x2,y2)) ? (Make(x1,y1)) : (Make(x2,y2)));
	}
	if(Comp(y1,y2))return Make(x0,y1);
	double k1 = (y1 - y2) / (x1 - x2),b1 = y1 - k1 * x1;
	double k2 = -1.0 / k1,b2 = y0 - k2 * x0;
	P Temp;Temp.first = (b2 - b1) / (k1 - k2);Temp.second = k1 * Temp.first + b1;
	return Temp;
}

P QAQInt(int k,P a){
	double x1 = Ge[k].u[0],y1 = Ge[k].u[1],x2 = Ge[k].v[0],y2 = Ge[k].v[1];
	double x0 = a.first , y0 = a.second;
	if(x1 == x2){
		if(y0 >= y1 && y0 <= y2)return Make(x1,y0);
	}
	double k1 = (y1 - y2) / (x1 - x2),b1 = y1 - k1 * x1;
	double k2 = -1.0 / k1,b2 = y0 - k2 * x0;
	P Temp;Temp.first = (b2 - b1) / (k1 - k2);Temp.second = k1 * Temp.first + b1;
	if(OnLine(k,Temp,1))return Temp;
	else {
		if(Dis(a,Make(x1,y1)) < Dis(a,Make(x2,y2)))return Make(x1,y1);
		else return Make(x2,y2);	
	}		
}

double CalDis(int t,P c){//Update 2017/3/10 20:14 Shit!This is A MisTake!
	double x0 = c.first,y0 = c.second;
	double x1 = Ge[t].u[0],y1 = Ge[t].u[1],x2 = Ge[t].v[0],y2 = Ge[t].v[1];
	if(x1 == x2){
		if(y0 >= y1 && y0 <= y2)return fabs(x1 - x0);
		else return min( Dis(Make(x1,y1),c) , Dis(Make(x2,y2),c) );
	}
	double k = (y1 - y2) / (x1 - x2),b = y1 - k * x1,x = c.first,y = c.second;
	P r = CalInt(t,c);
	if(OnLine(t,r,1)){return (fabs(k * x - y + b)) / (sqrt(k * k + 1.0));}
	else return min( Dis(Make(x1,y1),c) , Dis(Make(x2,y2),c) );
}

bool InG(int k,P a){double x = a.first,y = a.second;int res = 0;
	for(int i = l[k];i <= r[k];i++){
		double x1 = Ge[i].u[0],y1 = Ge[i].u[1];
		double x2 = Ge[i].v[0],y2 = Ge[i].v[1],kk = Ge[i].k,bb = Ge[i].b;
		if(y1 > y2){swap(x1,x2);swap(y1,y2);}
		if(OnLine(i,a,1))return 1;
		if(y1==y2 && y2 == y)continue;
		bool p = (kk > 0 && kk * x + bb > y) || (kk < 0 && kk * x + bb < y) || (Ge[i].u[0] == Ge[i].v[0] && Ge[i].u[0] <= x);
		if(y >= y1 && y <= y2 && y != y1 && p)res += 1;
	}
	return res % 2 == 1;
}

P CalMin(P x,P &X,double &y){//Update 2017/3/10 21:05 Again Wrong (three times)
	int kk = 0;
	for(int i = 1;i <= cnt;i++){
		P W = CalInt(i,x);
		if(CalDis(i,x) < y){
			y = CalDis(i,x);
			X = QAQInt(i,x);
		}
	}
}

P CalLineInt(int x,int w){
	double k1 = e[x].k,k2 = Ge[w].k;
	double b1 = e[x].b,b2 = Ge[w].b;
	if(e[x].u[0] == e[x].v[0]){
		P Temp;Temp.first = e[x].u[0];Temp.second = Temp.first * k2 + b2;
		return Temp;
	}
	if(Ge[w].u[0] == Ge[w].v[0]){
		P Temp;Temp.first = Ge[w].u[0];Temp.second = Temp.first * k1 + b2;	
	}
	P Temp;Temp.first = (b2 - b1) / (k1 - k2);Temp.second = Temp.first * k1 + b1;
	return Temp;
}

bool InLine(int w,int x){
	for(int i = l[w];i <= r[w];i++){
		if(Ge[i].k == e[x].k)continue;
		P Int = CalLineInt(x,i);double xx = Int.first;double yy = Int.second;
		if(OnLine(i,Int,1) && OnLine(x,Int,0)){
			return 1;
		}
	}
	return 0;
}

void CalAns(double &ans,P x){
	for(int i = 1;i <= c;i++)if(InG(i,x)){ans = 0.0;return;}
	for(int i = 1;i <= cnt;i++)ans = min(ans,CalDis(i,x));
}

int main(){
	freopen("flightsafety.in","r",stdin);
	freopen("flightsafety.out","w",stdout);
	scanf("%d",&T);
	while(T--){
		int h = 1,t = 0;
		tot = 0,cnt = 0;Res = 0.0;
	    scanf("%d%d",&c,&n);double x1,y1;
	    for(int i = 1;i <= n;i++){
	    	double x,y;scanf("%lf%lf",&x,&y);
	    	if(i != 1){
	    		e[++tot].u[0] = x1;e[tot].u[1] = y1;
	    		e[tot].v[0] = x;e[tot].v[1] = y;
	    	}x1 = x;y1 = y;
	    }
	    
	    for(int i = 1;i <= c;i++){
	    	scanf("%d",&m);
			double x1,y1;l[i] = cnt + 1;
	    	for(int j = 1;j <= m;j++){
	    		scanf("%lf%lf",&G[i].x[j],&G[i].y[j]);
	    		if(j != 1){Ge[++cnt].u[0] = x1;Ge[cnt].u[1] = y1;
	    			Ge[cnt].v[0] = G[i].x[j];Ge[cnt].v[1] = G[i].y[j];
	    		}x1 = G[i].x[j];y1 = G[i].y[j];
	    	}Ge[++cnt].u[0] = G[i].x[m];Ge[cnt].u[1] = G[i].y[m];r[i] = cnt;
	    	Ge[cnt].v[0] = G[i].x[1];Ge[cnt].v[1] = G[i].y[1];
	    }
	    
	    for(int i = 1;i <= cnt;i++){
	    	double x1 = Ge[i].u[0],y1 = Ge[i].u[1];
	    	double x2 = Ge[i].v[0],y2 = Ge[i].v[1];
	    	if(y1 > y2){swap(Ge[i].u[1],Ge[i].v[1]);swap(Ge[i].u[0],Ge[i].v[0]);}
	    	Ge[i].k = (y2 - y1) / (x2 - x1);
	    	Ge[i].b = y1 - x1 * Ge[i].k;	
	    }
	    
	    for(int i = 1;i <= tot;i++){int pd = 0;
	    	P a;a.first = e[i].u[0];a.second = e[i].u[1];
	    	P b;b.first = e[i].v[0];b.second = e[i].v[1];
	    	e[i].k = (b.second - a.second) / (b.first - a.first);
	    	e[i].b = a.second - a.first * e[i].k;
	    	for(int j = 1;j <= c;j++)if(InG(j,a) && InG(j,b) && !InLine(j,i)){pd = 1;break;}
	    	if(!pd){Q[++t] = i;}
		}
	    while(h <= t){
			int now = Q[h];
	    	P a,A;a.first = e[now].u[0],a.second = e[now].u[1];double xa = INF;
	    	P b,B;b.first = e[now].v[0],b.second = e[now].v[1];double xb = INF;
	    	for(int i = 1;i <= c;i++)if(InG(i,a)){xa = 0;A = a;break;}
	    	for(int i = 1;i <= c;i++)if(InG(i,b)){xb = 0;B = b;break;}
	    	if(xa == INF)CalMin(a,A,xa);
			if(xb == INF)CalMin(b,B,xb);
	    	double ans = 0.0;
	    	P L,R,Mid;
			L.first = a.first;L.second = a.second;
			R.first = b.first;R.second = b.second;
	    	while(Dis(L,R) > eps){
	    		Mid.first = (L.first + R.first) / 2.0;
				Mid.second = (L.second + R.second) / 2.0;
	    		if(Dis(Mid,A) > Dis(B,Mid))R = Mid;
	    		else L = Mid;
	    	}
	    	double ll = max(Dis(Mid,A),Dis(Mid,B));
			if(ll > Res + eps){
		    	P C;C.first = (a.first + b.first) / 2.0;C.second = (a.second + b.second) / 2.0;
		    	ans = INF;CalAns(ans,C);
				Res = max(ans,Res);
			    e[++tot].u[0] = e[now].u[0];e[tot].u[1] = e[now].u[1];
			    e[tot].v[0] = C.first;e[tot].v[1] = C.second;Q[++t] = tot;
			    if(t == 21000)t = 1;
			    e[++tot].u[0] = C.first;e[tot].u[1] = C.second;
			    e[tot].v[0] = e[now].v[0];e[tot].v[1] = e[now].v[1];
			    Q[++t] = tot;if(t == 21000)t = 1;
	    	}h++;if(h == 21000)h = 1;
	    }
		printf("%.6lf\n",Res);
	}
	return 0;
}