记录编号 375906 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 大灾变 最终得分 100
用户昵称 GravatarNew World 是否通过 通过
代码语言 C++ 运行时间 5.008 s
提交时间 2017-02-26 10:17:22 内存使用 72.41 MiB
显示代码纯文本
  1. #include <cmath>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <algorithm>
  6. using namespace std;
  7. #define LL long long
  8. #define Inf 2e100
  9. #define eps 1e-12
  10. const int maxn=1050000;
  11. struct Point{
  12. double x,y;
  13. Point(double xx=0,double yy=0){x=xx;y=yy;}
  14. void input(){scanf("%lf%lf",&x,&y);}
  15. void output(){printf("<<%.3lf %.3lf>>",x,y);}
  16. };
  17. typedef Point Vector;
  18.  
  19. int dcmp(double x)
  20. {return fabs(x)<eps ? 0 : x>0 ? 1 :-1;}
  21.  
  22. bool operator == (Vector A,double x)
  23. {return dcmp(A.x-x)==0 && dcmp(A.y-x)==0;}
  24.  
  25. bool operator < (Point A,Point B)
  26. {return A.x!=B.x ? A.x<B.x : A.y<B.y;}
  27.  
  28. Vector operator - (Point A,Point B)
  29. {return Vector(A.x-B.x,A.y-B.y);}
  30.  
  31. Point operator + (Point A,Vector B)
  32. {return Point(A.x+B.x,A.y+B.y);}
  33.  
  34. Vector operator * (Vector A,double x)
  35. {return Vector(A.x*x,A.y*x);}
  36.  
  37. double Cross(Vector A,Vector B)
  38. {return A.x*B.y-A.y*B.x;}
  39.  
  40. double Dot(Vector A,Vector B)
  41. {return A.x*B.x+A.y*B.y;}
  42.  
  43. double Length(Vector A)
  44. {return sqrt(Dot(A,A));}
  45.  
  46. struct Line{
  47. Point P;Vector v;
  48. double ang;
  49. Line(){};
  50. Line(Point A,Vector B){
  51. P=A;v=B;
  52. ang=atan2(v.y,v.x);
  53. }
  54. bool operator < (const Line & A)const{
  55. return ang<A.ang;
  56. }
  57. };
  58.  
  59. bool OnLeft(Line L,Point P)
  60. {return dcmp(Cross(L.v,P-L.P))>=0;}
  61.  
  62. Point LineInterSection(Line A,Line B){
  63. if(B.v==0 && A.v==0)return Point(Inf,Inf);
  64. if(B.v==0){
  65. if(dcmp(Cross(A.v,B.P-A.P))==0)return B.P;
  66. }
  67. if(A.v==0){
  68. if(dcmp(Cross(B.v,A.P-B.P))==0)return A.P;
  69. }
  70. Vector u=A.P-B.P;
  71. double t=Cross(B.v,u)/Cross(A.v,B.v);
  72. return A.P+A.v*t;
  73. }
  74.  
  75. int HalfPlaneInterSection(Line *L,int n,Point *poly){
  76. sort(L,L+n);
  77. Point *p=new Point[n];
  78. Line *q=new Line[n];
  79. int head,tail;
  80. q[head=tail=0]=L[0];
  81. for(int i=1;i<n;i++){
  82. while(head<tail && !OnLeft(L[i],p[tail-1]))tail--;
  83. while(head<tail && !OnLeft(L[i],p[head ]))head++;
  84. q[++tail]=L[i];
  85. if(dcmp(Cross(q[tail].v,q[tail-1].v))==0){
  86. tail--;
  87. if(OnLeft(q[tail],L[i].P))q[tail]=L[i];
  88. }
  89. p[tail-1]=LineInterSection(q[tail],q[tail-1]);
  90. }
  91. while(head<tail && !OnLeft(q[head],p[tail-1]))tail--;
  92. if(tail-head<=1)return 0;
  93. p[tail]=LineInterSection(q[tail],q[head]);
  94. int m=0;
  95. for(int i=head;i<=tail;i++)poly[++m]=p[i];
  96. return m;
  97. }
  98.  
  99. int n,cnt;
  100. Point p[maxn],poly[maxn];
  101. Line L[maxn];
  102. void Init();
  103. int main(){
  104. freopen("cataclysm.in","r",stdin);
  105. freopen("cataclysm.out","w",stdout);
  106. Init();
  107. return 0;
  108. }
  109. void Init(){
  110. scanf("%d",&n);
  111. for(int i=1;i<=n;i++)p[i].input();
  112. sort(p+1,p+n+1);
  113. for(int i=1;i<n;i++)
  114. L[cnt++]=Line(p[i],p[i+1]-p[i]);
  115. L[cnt++]=Line(p[n],Vector(0,1));
  116. L[cnt++]=Line(p[1],Vector(0,-1));
  117. L[cnt++]=Line(Point(0,Inf),Vector(-1,0));
  118. int m=HalfPlaneInterSection(L,cnt,poly);
  119. Point flyer;flyer.y=Inf;
  120. for(int i=1;i<=m;i++)
  121. if(dcmp(poly[i].y-flyer.y)<0)
  122. flyer=poly[i];
  123. int i=1,j=1;m--;
  124. //for(int i=1;i<=m;i++)poly[i].output();
  125. Point Fire;double ans=Inf;
  126. //从山脉对应下凸壳
  127. while(p[i+1].x<poly[1].x)i++;
  128. for(;i<=n;i++){
  129. if(p[i].x>poly[m].x)break;
  130. while(poly[j+1].x<p[i].x)j++;
  131. Line l1=Line(p[i],Vector(0,1));
  132. Line l2=Line(poly[j],poly[j+1]-poly[j]);
  133. Point Inter=LineInterSection(l1,l2);
  134. //Inter.output();
  135. double len=Length(Inter-p[i]);
  136. if(dcmp(len-ans)==-1){
  137. Fire=Inter;ans=len;
  138. }
  139. }
  140. //从下凸壳对应山脉
  141. i=1;j=1;
  142. while(p[i+1].x<poly[1].x)i++;
  143. for(;j<=m;j++){
  144. if(p[i].x>poly[m].x)break;
  145. while(p[i+1].x<poly[j].x)i++;
  146. Line l1=Line(poly[j],Vector(0,-1));
  147. Line l2=Line(p[i],p[i+1]-p[i]);
  148. Point Inter=LineInterSection(l1,l2);
  149. double len=Length(Inter-poly[j]);
  150. if(dcmp(len-ans)==-1){
  151. Fire=poly[j];ans=len;
  152. }
  153. }
  154. printf("%.2lf %.2lf\n",Fire.x,Fire.y);
  155. printf("%.2lf %.2lf\n",flyer.x,flyer.y);
  156. //printf("%d\n",m);
  157. }