记录编号 381124 评测结果 AE
题目名称 1700.[NWERC2007]飞行安全 最终得分 50
用户昵称 sssSSSay 是否通过 未通过
代码语言 C++ 运行时间 0.185 s
提交时间 2017-03-10 21:27:05 内存使用 2.71 MiB
显示代码纯文本
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>

#define INF 100000000005
#define eps 1e-11
#define Make make_pair
#define rr 6

using namespace std;

typedef pair<double,double> P;

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

int T,n,c,tot,cnt,m,l[210],r[210];P L;
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;
//	cout<<k1 * x0 + b1 - y0 <<' '<<y0<<endl;
	if(fabs(k1 * x0 + b1 - y0) > eps)return 0;
//	printf("!");
	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;
//	cout<<k1<<endl;
	
	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);
//	printf("r(%.2lf,%.2lf) => %d\n",r.first,r.second,OnLine(t,r,1));
	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);}
//		printf("%d\n",i);
		if(OnLine(i,a,1))return 1;
//		printf("!");
		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;
	}
//	if(res % 2 == 0)printf("\n!\n");
	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);
//		printf("%d a(%.2lf,%.2lf) b(%.2lf,%.2lf) Int(%.2lf,%.2lf) Dis:%.6lf\n",i,Ge[i].u[0],Ge[i].u[1],Ge[i].v[0],Ge[i].v[1],W.first,W.second,CalDis(i,x));
		if(CalDis(i,x) < y){
			y = CalDis(i,x);
			X = QAQInt(i,x);
//			printf(">>>(%.6lf)\n",y);
		}
	}
//	printf("(%.6lf)  ==? (%.6lf)\n",Dis(X,x),CalDis(kk,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;
		}
	}
//	printf("!");
	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--){
		queue <int> Q;
		tot = 0,cnt = 0;Res = 0.0;
	    scanf("%d%d",&c,&n);double x1,y1;
//	    if(T == rr)printf("%d %d\n",c,n);
	    for(int i = 1;i <= n;i++){
	    	double x,y;scanf("%lf%lf",&x,&y);
//	    	if(T == rr)cout<<x<<' '<<y<<endl;
//	    	x += eps;y -= eps;
	    	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);
//	    	if(T == rr)printf("%d\n",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(T == rr)cout<<G[i].x[j]<<' '<<G[i].y[j]<<endl;
	    		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.push(i);
		}
//		P xx,X;double mi = INF;xx.first = 20.0;xx.second = 40.0;
//		P ww = CalInt(12,xx);
//		printf("%.6lf (%.2lf,%.2lf)\n",CalDis(12,xx),ww.first,ww.second);
//		CalMin(xx,X,mi);
//		printf("(%.2lf,%.2lf) Dis = %.6lf\n",X.first,X.second,mi);
//		return 0;
	    while(!Q.empty()){
//	    	printf("!");
			int now = Q.front();Q.pop();
	    	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;
//			printf("a(%.2lf,%.2lf) b(%.2lf,%.2lf) A(%.2lf,%.2lf) B(%.2lf,%.2lf)\n",a.first,a.second,b.first,b.second,A.first,A.second,B.first,B.second);
//			return 0;
//			printf("(%.2lf,%.2lf) => (%.2lf,%.2lf) = %.6lf\n",L.first,L.second,R.first,R.second,Dis(L,R));
//			return 0;
	    	while(Dis(L,R) > eps){
	    		Mid.first = (L.first + R.first) / 2.0;
				Mid.second = (L.second + R.second) / 2.0;
//				printf("L(%.2lf,%.2lf) R(%.2lf,%.2lf) Mid(%.2lf,%.2lf)\n",L.first,L.second,R.first,R.second,Mid.first,Mid.second);
//	    		printf(">>dis1(%.6lf) dis2(%.6lf)\n",Dis(Mid,A),Dis(Mid,B));
//				printf("@@A(%.2lf,%.2lf) B(%.2lf,%.2lf)\n",A.first,A.second,B.first,B.second);
//				printf("(%.2lf,%.2lf)\n",Mid.first,Mid.second);
	    		if(Dis(Mid,A) > Dis(B,Mid))R = Mid;
	    		else L = Mid;
	    	}
//	    	printf("%.6lf %.6lf\n",Dis(Mid,A),Dis(Mid,B));
//	    	printf("(%.2lf,%.2lf)\n",Mid.first,Mid.second);
	    	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;
			    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.push(tot - 1);Q.push(tot);
	    	}
//	    	printf("---------------------\n");
	    }
		printf("%.6lf\n",Res);
	}
	return 0;
}

/*
1
2 2
1 1
19 19
3
0 15
15 0
0 0
3
5 20
20 5
20 20
*/
/*
1
2 3
12 4
16 17
3 9
4
1 0
4 19
19 14
6 12
3
10 10
5 3
18 2
*/
/*
1
2 3
2 10
16 7
16 14
3
5 14
2 5
1 11
5
18 14
13 17
11 9
18 4
14 12
*/
/*
1
2 2
1 67
1 -25
5
-3 58
-20 52
-20 -3
-3 -14
-95 30
9
-19 -23
47 -15
62 28
51 69
-34 63
80 80
85 0
67 -27
-38 -28
*/