点击打开链接

题意:

按顺序给出一小岛(多边形)的点

求岛上某点离海最远的距离

解法:

不断的收缩多边形(求半平面交)

直到无限小

二分收缩的距离即可

如图

  1. //大白p263
  2. #include <cmath>
  3. #include <cstdio>
  4. #include <cstring>
  5. #include <string>
  6. #include <queue>
  7. #include <functional>
  8. #include <set>
  9. #include <iostream>
  10. #include <vector>
  11. #include <algorithm>
  12. using namespace std;
  13. const double eps=1e-7;//精度
  14. const int INF=0x3f3f3f3f;
  15. const double PI=acos(-1.0);
  16. int dcmp(double x){//判断double等于0或。。。
  17. if(fabs(x)<eps)return 0;else return x<0?-1:1;
  18. }
  19. struct Point{
  20. double x,y;
  21. Point(double x=0,double y=0):x(x),y(y){}
  22. };
  23. typedef Point Vector;
  24. typedef vector<Point> Polygon;
  25. Vector operator+(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}//向量+向量=向量
  26. Vector operator-(Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}//点-点=向量
  27. Vector operator*(Vector a,double p){return Vector(a.x*p,a.y*p);}//向量*实数=向量
  28. Vector operator/(Vector a,double p){return Vector(a.x/p,a.y/p);}//向量/实数=向量
  29. bool operator<( const Point& A,const Point& B ){return dcmp(A.x-B.x)<0||(dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)<0);}
  30. bool operator==(const Point&a,const Point&b){return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;}
  31. bool operator!=(const Point&a,const Point&b){return a==b?false:true;}
  32. struct Segment{
  33. Point a,b;
  34. Segment(){}
  35. Segment(Point _a,Point _b){a=_a,b=_b;}
  36. bool friend operator<(const Segment& p,const Segment& q){return p.a<q.a||(p.a==q.a&&p.b<q.b);}
  37. bool friend operator==(const Segment& p,const Segment& q){return (p.a==q.a&&p.b==q.b)||(p.a==q.b&&p.b==q.a);}
  38. };
  39. struct Circle{
  40. Point c;
  41. double r;
  42. Circle(){}
  43. Circle(Point _c, double _r):c(_c),r(_r) {}
  44. Point point(double a)const{return Point(c.x+cos(a)*r,c.y+sin(a)*r);}
  45. bool friend operator<(const Circle& a,const Circle& b){return a.r<b.r;}
  46. };
  47. struct Line{
  48. Point p;
  49. Vector v;
  50. double ang;
  51. Line() {}
  52. Line(const Point &_p, const Vector &_v):p(_p),v(_v){ang = atan2(v.y, v.x);}
  53. bool operator<(const Line &L)const{return ang < L.ang;}
  54. };
  55. double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}//|a|*|b|*cosθ 点积
  56. double Length(Vector a){return sqrt(Dot(a,a));}//|a| 向量长度
  57. double Angle(Vector a,Vector b){return acos(Dot(a,b)/Length(a)/Length(b));}//向量夹角θ
  58. double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}//叉积 向量围成的平行四边形的面积
  59. double Area2(Point a,Point b,Point c){return Cross(b-a,c-a);}//同上 参数为三个点
  60. double DegreeToRadius(double deg){return deg/180*PI;}
  61. double GetRerotateAngle(Vector a,Vector b){//向量a顺时针旋转theta度得到向量b的方向
  62. double tempa=Angle(a,Vector(1,0));
  63. if(a.y<0) tempa=2*PI-tempa;
  64. double tempb=Angle(b,Vector(1,0));
  65. if(b.y<0) tempb=2*PI-tempb;
  66. if((tempa-tempb)>0) return tempa-tempb;
  67. else return tempa-tempb+2*PI;
  68. }
  69. double torad(double deg){return deg/180*PI;}//角度化为弧度
  70. Vector Rotate(Vector a,double rad){//向量逆时针旋转rad弧度
  71. return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
  72. }
  73. Vector Normal(Vector a){//计算单位法线
  74. double L=Length(a);
  75. return Vector(-a.y/L,a.x/L);
  76. }
  77. Point GetLineProjection(Point p,Point a,Point b){//点在直线上的投影
  78. Vector v=b-a;
  79. return a+v*(Dot(v,p-a)/Dot(v,v));
  80. }
  81. Point GetLineIntersection(Point p,Vector v,Point q,Vector w){//求直线交点 有唯一交点时可用
  82. Vector u=p-q;
  83. double t=Cross(w,u)/Cross(v,w);
  84. return p+v*t;
  85. }
  86. int ConvexHull(Point* p,int n,Point* sol){//计算凸包
  87. sort(p,p+n);
  88. int m=0;
  89. for(int i=0;i<n;i++){
  90. while(m>1&&Cross(sol[m-1]-sol[m-2],p[i]-sol[m-2])<=0) m--;
  91. sol[m++]=p[i];
  92. }
  93. int k=m;
  94. for(int i=n-2;i>=0;i--){
  95. while(m>k&&Cross(sol[m-1]-sol[m-2],p[i]-sol[m-2])<=0) m--;
  96. sol[m++]=p[i];
  97. }
  98. if(n>0) m--;
  99. return m;
  100. }
  101. double Heron(double a,double b,double c){//海伦公式
  102. double p=(a+b+c)/2;
  103. return sqrt(p*(p-a)*(p-b)*(p-c));
  104. }
  105. bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){//线段规范相交判定
  106. double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1);
  107. double c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
  108. return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
  109. }
  110. double CutConvex(const int n,Point* poly, const Point a,const Point b, vector<Point> result[3]){//有向直线a b 切割凸多边形
  111. vector<Point> points;
  112. Point p;
  113. Point p1=a,p2=b;
  114. int cur,pre;
  115. result[0].clear();
  116. result[1].clear();
  117. result[2].clear();
  118. if(n==0) return 0;
  119. double tempcross;
  120. tempcross=Cross(p2-p1,poly[0]-p1);
  121. if(dcmp(tempcross)==0) pre=cur=2;
  122. else if(tempcross>0) pre=cur=0;
  123. else pre=cur=1;
  124. for(int i=0;i<n;i++){
  125. tempcross=Cross(p2-p1,poly[(i+1)%n]-p1);
  126. if(dcmp(tempcross)==0) cur=2;
  127. else if(tempcross>0) cur=0;
  128. else cur=1;
  129. if(cur==pre){
  130. result[cur].push_back(poly[(i+1)%n]);
  131. }
  132. else{
  133. p1=poly[i];
  134. p2=poly[(i+1)%n];
  135. p=GetLineIntersection(p1,p2-p1,a,b-a);
  136. points.push_back(p);
  137. result[pre].push_back(p);
  138. result[cur].push_back(p);
  139. result[cur].push_back(poly[(i+1)%n]);
  140. pre=cur;
  141. }
  142. }
  143. sort(points.begin(),points.end());
  144. if(points.size()<2){
  145. return 0;
  146. }
  147. else{
  148. return Length(points.front()-points.back());
  149. }
  150. }
  151. double DistanceToSegment(Point p,Segment s){//点到线段的距离
  152. if(s.a==s.b) return Length(p-s.a);
  153. Vector v1=s.b-s.a,v2=p-s.a,v3=p-s.b;
  154. if(dcmp(Dot(v1,v2))<0) return Length(v2);
  155. else if(dcmp(Dot(v1,v3))>0) return Length(v3);
  156. else return fabs(Cross(v1,v2))/Length(v1);
  157. }
  158. bool isPointOnSegment(Point p,Segment s){
  159. return dcmp(Cross(s.a-p,s.b-p))==0&&dcmp(Dot(s.a-p,s.b-p))<0;
  160. }
  161. int isPointInPolygon(Point p, Point* poly,int n){//点与多边形的位置关系
  162. int wn=0;
  163. for(int i=0;i<n;i++){
  164. Point& p2=poly[(i+1)%n];
  165. if(isPointOnSegment(p,Segment(poly[i],p2))) return -1;//点在边界上
  166. int k=dcmp(Cross(p2-poly[i],p-poly[i]));
  167. int d1=dcmp(poly[i].y-p.y);
  168. int d2=dcmp(p2.y-p.y);
  169. if(k>0&&d1<=0&&d2>0)wn++;
  170. if(k<0&&d2<=0&&d1>0)wn--;
  171. }
  172. if(wn) return 1;//点在内部
  173. else return 0;//点在外部
  174. }
  175. double PolygonArea(Point* p,int n){//多边形有向面积
  176. double area=0;
  177. for(int i=1;i<n-1;i++)
  178. area+=Cross(p[i]-p[0],p[i+1]-p[0]);
  179. return area/2;
  180. }
  181. int GetLineCircleIntersection(Line L,Circle C,Point& p1,Point& p2){//圆与直线交点 返回交点个数
  182. double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y-C.c.y;
  183. double e = a*a + c*c, f = 2*(a*b+c*d), g = b*b + d*d -C.r*C.r;
  184. double delta = f*f - 4*e*g;
  185. if(dcmp(delta) < 0) return 0;//相离
  186. if(dcmp(delta) == 0) {//相切
  187. p1=p1=C.point(-f/(2*e));
  188. return 1;
  189. }//相交
  190. p1=(L.p+L.v*(-f-sqrt(delta))/(2*e));
  191. p2=(L.p+L.v*(-f+sqrt(delta))/(2*e));
  192. return 2;
  193. }
  194. double rotating_calipers(Point *ch,int n)//旋转卡壳
  195. {
  196. int q=1;
  197. double ans=0;
  198. ch[n]=ch[0];
  199. for(int p=0;p<n;p++)
  200. {
  201. while(Cross(ch[q+1]-ch[p+1],ch[p]-ch[p+1])>Cross(ch[q]-ch[p+1],ch[p]-ch[p+1]))
  202. q=(q+1)%n;
  203. ans=max(ans,max(Length(ch[p]-ch[q]),Length(ch[p+1]-ch[q+1])));
  204. }
  205. return ans;
  206. }
  207. Polygon CutPolygon(Polygon poly,Point a,Point b){//用a->b切割多边形 返回左侧
  208. Polygon newpoly;
  209. int n=poly.size();
  210. for(int i=0;i<n;i++){
  211. Point c=poly[i];
  212. Point d=poly[(i+1)%n];
  213. if(dcmp(Cross(b-a,c-a))>=0) newpoly.push_back(c);
  214. if(dcmp(Cross(b-a,c-d))!=0){
  215. Point ip=GetLineIntersection(a,b-a,c,d-c);
  216. if(isPointOnSegment(ip,Segment(c,d))) newpoly.push_back(ip);
  217. }
  218. }
  219. return newpoly;
  220. }
  221. int GetCircleCircleIntersection(Circle c1,Circle c2,Point& p1,Point& p2){//求两圆相交
  222. double d=Length(c1.c-c2.c);
  223. if(dcmp(d)==0){
  224. if(dcmp(c1.r-c2.r)==0) return -1;//两圆重合
  225. return 0;
  226. }
  227. if(dcmp(c1.r+c2.r-d)<0) return 0;
  228. if(dcmp(fabs(c1.r-c2.r)-d)>0) return 0;
  229. double a=Angle(c2.c-c1.c,Vector(1,0));
  230. double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
  231. p1=c1.point(a-da);p2=c1.point(a+da);
  232. if(p1==p2) return 1;
  233. return 2;
  234. }
  235. bool isPointOnleft(Point p,Line L){return dcmp(Cross(L.v,p-L.p))>0;}
  236. int HalfplaneIntersection(Line *L,int n,Point* poly){//半平面交
  237. sort(L,L+n);
  238. int first,last;
  239. Point* p=new Point[n];
  240. Line* q=new Line[n];
  241. q[first=last=0]=L[0];
  242. for(int i=1;i<n;i++){
  243. while(first<last&&!isPointOnleft(p[last-1],L[i])) last--;
  244. while(first<last&&!isPointOnleft(p[first],L[i])) first++;
  245. q[++last]=L[i];
  246. if(dcmp(Cross(q[last].v,q[last-1].v))==0){
  247. last--;
  248. if(isPointOnleft(L[i].p,q[last])) q[last]=L[i];
  249. }
  250. if(first<last) p[last-1]=GetLineIntersection(q[last-1].p,q[last-1].v,q[last].p,q[last].v);
  251. }
  252. while(first<last&&!isPointOnleft(p[last-1],q[first])) last--;
  253. if(last-first<=1) return 0;
  254. p[last]=GetLineIntersection(q[last].p,q[last].v,q[first].p,q[first].v);
  255. int m=0;
  256. for(int i=first;i<=last;i++) poly[m++]=p[i];
  257. return m;
  258. }
  259. //两点式化为一般式A = b.y-a.y, B = a.x-b.x, C = -a.y*(B)-a.x*(A);
  260. //--------------------------------------
  261. //--------------------------------------
  262. //--------------------------------------
  263. //--------------------------------------
  264. //--------------------------------------
  265. Point p[200],poly[200];
  266. Line L[200];
  267. Vector v[200],v2[200];
  268. int main(){
  269. int n;
  270. while(scanf("%d",&n)&&n){
  271. int m,x,y;
  272. for(int i=0;i<n;i++)
  273. scanf("%lf%lf",&p[i].x,&p[i].y);
  274. for(int i=0;i<n;i++){
  275. v[i]=p[(i+1)%n]-p[i];
  276. v2[i]=Normal(v[i]);
  277. }
  278. double left=0,right=20000;
  279. while(dcmp(right-left)>0){
  280. double mid=left+(right-left)/2;
  281. for(int i=0;i<n;i++) L[i]=Line(p[i]+v2[i]*mid,v[i]);
  282. m=HalfplaneIntersection(L,n,poly);
  283. if(!m) right=mid;
  284. else left=mid;
  285. }
  286. printf("%.6lf\n",left);
  287. }
  288. return 0;
  289. }

1396 - Most Distant Point from the Sea的更多相关文章

  1. POJ 3525/UVA 1396 Most Distant Point from the Sea(二分+半平面交)

    Description The main land of Japan called Honshu is an island surrounded by the sea. In such an isla ...

  2. uva 1396 - Most Distant Point from the Sea

    半平面的交,二分的方法: #include<cstdio> #include<algorithm> #include<cmath> #define eps 1e-6 ...

  3. POJ 3525 Most Distant Point from the Sea [半平面交 二分]

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5153   ...

  4. LA 3890 Most Distant Point from the Sea(半平面交)

    Most Distant Point from the Sea [题目链接]Most Distant Point from the Sea [题目类型]半平面交 &题解: 蓝书279 二分答案 ...

  5. 【POJ】【3525】Most Distant Point from the Sea

    二分+计算几何/半平面交 半平面交的学习戳这里:http://blog.csdn.net/accry/article/details/6070621 然而这题是要二分长度r……用每条直线的距离为r的平 ...

  6. POJ 3525 Most Distant Point from the Sea (半平面交+二分)

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3476   ...

  7. POJ3525-Most Distant Point from the Sea(二分+半平面交)

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3955   ...

  8. POJ 3525 Most Distant Point from the Sea (半平面交)

    Description The main land of Japan called Honshu is an island surrounded by the sea. In such an isla ...

  9. 【POJ 3525】Most Distant Point from the Sea(直线平移、半平面交)

    按逆时针顺序给出n个点,求它们组成的多边形的最大内切圆半径. 二分这个半径,将所有直线向多边形中心平移r距离,如果半平面交不存在那么r大了,否则r小了. 平移直线就是对于向量ab,因为是逆时针的,向中 ...

随机推荐

  1. Ajax中XML和JSON格式的优劣比较

    刚做完一个小的使用Ajax的项目.整个小项目使用JavaScript做客户端,使用PHP做服务器端.利用xmlHttpRequest组件作为交互工具,利用XML作为数据传输的格式.做完后基本做一个简单 ...

  2. 括号匹配算法 C语言实现

    #include <stdio.h> #include <malloc.h> //malloc,realloc #include <math.h> //含有over ...

  3. 引用(ajaxfileupload.js) ajaxfileupload.js报这错jQuery.handleError is not a function

    jQuery.handleError is not a function 原因是,经测试handlerError只在jquery-1.4.2之前的版本中存在,jquery-1.6 和1.7中都没有这个 ...

  4. SQL Server 执行计划重编译的两大情况

    1.与正确性相关的重编译 1.为表或视图添加列,删除列. 2.为表添加约束.默认值.规则,删除约束.默认值.规则. 3.为表或视图添加索引. 4.如果计划用不用索引而这个索引被删除. 5.删除表中的统 ...

  5. SQL Server 固定角色

    1. 查看固定服务器角色 execute sp_helpsrvrole; 管理: execute master..sp_addsrvrolemember @logingName='neeky' @ro ...

  6. 蓝桥杯之K好数问题

    问题描述 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数.求L位K进制数中K好数的数目.例如K = 4,L = 2的时候,所有K好数为11.13.20.22 ...

  7. hdu--1800--字典树&&其他

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1800 根据题意可知:意思是有若干个飞行员,需要在扫帚上练习飞行,每个飞行员具有不同的等级,且等级高的飞 ...

  8. Android之SplashActivity的巧妙之处

    众所周知,我们很多应用都会有一个SplashActivity,用来当作进入应用的第一个过度界面,显示一个logo信息.如下所示,是我的简洁天气的SplashActivity. 但是,它的作用仅仅只是用 ...

  9. Android 启动Activity的方式

    Activity的启动分为两种方式,显示方式和隐式方式,显示方式就是在通过intent启动Activity时指定了Activity的包名和类名. 而隐式方式则在初始化Intent时仅仅指定action ...

  10. Jave中System.getProperty()获取的值

    java.version Java 执行时环境版本号 java.vendor Java 执行时环境供应商 java.vendor.url Java 供应商的 URL java.home Java 安装 ...