zoukankan      html  css  js  c++  java
  • Most Distant Point from the Sea POJ

    题目链接:https://vjudge.net/problem/POJ-3525

    思路:求凸包内最大圆的半径

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<math.h>
      6 #define eps 1e-8
      7 #define PI acos(-1.0)
      8 #define MAXN 110
      9 using namespace std;
     10 
     11 int n;
     12 
     13 int sgn(double x)
     14 { //符号函数
     15     if(fabs(x) < eps) return 0;
     16     if(x < 0) return -1;
     17     else return 1;
     18 }
     19 
     20 struct Point
     21 { //
     22     double x,y;
     23     Point(){}
     24     Point(double _x,double _y)
     25     {
     26         x = _x; y = _y;
     27     }
     28     Point operator -(const Point &b)const
     29     {
     30         return Point(x - b.x, y - b.y);
     31     }
     32     double operator ^(const Point &b)const
     33     { //叉积
     34         return x*b.y - y*b.x;
     35     }
     36     double operator *(const Point &b)const
     37     { //点积
     38         return x*b.x + y*b.y;
     39     }
     40 };
     41 
     42 struct Line
     43 { //向量 
     44     Point s,e; //两点
     45     double k; //斜率
     46     Line(){}
     47     Line(Point _s,Point _e)
     48     { //构造
     49         s = _s; e = _e;
     50         k = atan2(e.y - s.y,e.x - s.x);
     51     }
     52     Point operator &(const Line &b)const
     53     { //求两直线交点
     54         Point res = s;
     55         double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e));
     56         res.x += (e.x - s.x)*t;
     57         res.y += (e.y - s.y)*t;
     58         return res;
     59     }
     60 };
     61 
     62 Line Q[MAXN];
     63 Point p[MAXN]; //记录最初给的点集
     64 Line line[MAXN]; //由最初的点集生成直线的集合
     65 Point pp[MAXN]; //记录半平面交的结果的点集
     66 
     67 //半平面交,直线的左边代表有效区域
     68 bool HPIcmp(Line a,Line b)
     69 { //直线排序函数
     70     if(fabs(a.k - b.k) > eps)return a.k < b.k; //斜率排序
     71     
     72     return ((a.s - b.s)^(b.e - b.s)) < 0;
     73 }
     74 
     75 void HPI(Line line[], int n, Point res[], int &resn)
     76 { //line是半平面交的直线的集合 n是直线的条数 res是结果
     77 //的点集 resn是点集里面点的个数
     78     int tot = n;
     79     sort(line,line+n,HPIcmp);
     80     tot = 1;
     81     for(int i = 1;i < n;i++)
     82         if(fabs(line[i].k - line[i-1].k) > eps) //去掉斜率重复的
     83             line[tot++] = line[i];
     84     int head = 0, tail = 1;
     85     Q[0] = line[0];
     86     Q[1] = line[1];
     87     resn = 0;
     88     for(int i = 2; i < tot; i++)
     89     {
     90         if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps ||
     91            fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps)
     92             return;
     93         while(head < tail && (((Q[tail]&Q[tail-1]) -
     94                                line[i].s)^(line[i].e-line[i].s)) > eps)
     95             tail--;
     96         while(head < tail && (((Q[head]&Q[head+1]) -
     97                                line[i].s)^(line[i].e-line[i].s)) > eps)
     98             head++;
     99         Q[++tail] = line[i];
    100     }
    101     while(head < tail && (((Q[tail]&Q[tail-1]) -
    102                            Q[head].s)^(Q[head].e-Q[head].s)) > eps)
    103         tail--;
    104     while(head < tail && (((Q[head]&Q[head-1]) -
    105                            Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps)
    106         head++;
    107     if(tail <= head + 1) return;
    108     for(int i = head; i < tail; i++)
    109         res[resn++] = Q[i]&Q[i+1];
    110     if(head < tail - 1)
    111         res[resn++] = Q[head]&Q[tail];
    112 }
    113 
    114 double dist(Point a,Point b)
    115 { //两点间距离
    116     return sqrt((a-b)*(a-b));
    117 }
    118 
    119 void change(Point a,Point b,Point &c,Point &d,double p)
    120 { //将线段ab往左移动距离p,修改得到线段cd
    121     double len=dist(a,b);
    122     /*三角形相似推出下面公式*/
    123     double dx=(a.y-b.y)*p/len;
    124     double dy=(b.x-a.x)*p/len;
    125     c.x=a.x+dx; c.y=a.y+dy;
    126     d.x=b.x+dx; d.y=b.y+dy;
    127 }
    128 
    129 double BSearch()
    130 { //二分搜索 
    131     double l=0,r=100000;
    132     double ans=0;
    133     while(r-l>=eps)
    134     {
    135         double mid=(l+r)/2;
    136         for(int i=0;i < n;i++)
    137         {
    138             Point t1,t2;
    139             change(p[i],p[(i+1)%n],t1,t2,mid);
    140             line[i]=Line(t1,t2);
    141         }
    142         int resn;
    143         HPI(line,n,pp,resn);
    144         //等于0说明移多了
    145         if(resn==0) r=mid-eps;
    146         else l=mid+eps;
    147     }
    148     return l;
    149 }
    150 
    151 int main()
    152 {
    153     while(~scanf("%d",&n)&&n)
    154     {
    155         for(int i = 0;i < n;i++)
    156             scanf("%lf%lf",&p[i].x,&p[i].y);
    157         printf("%.6f
    ",BSearch());
    158     }
    159     return 0;
    160 }
     
  • 相关阅读:
    常用 Git 命令清单
    谈谈关于PHP的代码安全相关的一些致命知识
    九个Console命令,让 JS 调试更简单
    有趣的博客小工具
    利用fputcsv导出数据备份数据
    IT小天博客APP版本
    七牛云存储文件批量下载工具使用教程
    Mysql的常见几种错误:1045,1044
    我是一个线程
    两行代码快速创建一个iOS主流UI框架
  • 原文地址:https://www.cnblogs.com/Vampire6/p/12464514.html
Copyright © 2011-2022 走看看