zoukankan      html  css  js  c++  java
  • poj 3525 Most Distant Point from the Sea 多边形内切圆

    求多边形最大内接圆半径。
    半平面交+二分查找:把多边形的每条边向内推R的距离,若变幻之后的仍是一个多边形,说明距离R太小了,若无边说明R过大。
    这边有两个纯几何上的问题,就是如果求直线和平移直线。
    一、已知两点求直线ax+by+c=0:
            已知两点为A(x[i],y[i]),B(x[i+1],y[i+1]),取直线上的另外一点C(x,y),则有:
            (x-x[i])/(y-y[i])=(x[i+1]-x[i])/(y[i+1]-y[i]);
             化解得:
            x(y[i+1]-y[i])+y(x[i]-x[i+1])+x[i+1]y[i]-x[i]y[i+1]=0;
           即a=y[i+1]-y[i];
              b=x[i]-x[i+1];
              c=x[i+1]y[i]-x[i]y[i+1];
    二、如何平移直线:
    就拿最简单的过原点的直线y=(a/b)x的直线来讲吧(有常数项的直线和它类似)。
    该直线的倾斜角tan∠T=a/b;
                                    cos∠T=b/sqrt(a*a+b*b);
                                   sin∠T=a/sqrt(a*a+b*b);
             设直线平移了mid的距离,直线上的点(x,y)变幻为(x-x1,y-y1);
            x1,y1,mid三边可组成一个以mid为斜边的直角三角形;
            且x1=sin∠T*mid=a/sqrt(a*a+b*b)*mid;
               y1=cos∠T*mdi=b/sqrt(a*a+b*b)*mid;
    这样取原直线上的任意两点做如上的变幻,以新得到的这两点再做直线即可。
     
      1 #include<iostream>
      2 #include<cmath>
      3 using namespace std;
      4 const double pi=acos(-1.0);
      5 const int N=500;
      6 const double eps=1e-9;
      7 int n,m,s;
      8 struct point
      9 {
     10     double x,y;
     11 }p[N],q[N],input[N];
     12 int sig(double k)
     13 {
     14     return (k<-eps)?-1:(k>eps);
     15 }
     16 double dis(point a,point b)
     17 {
     18     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     19 }
     20 double xmule(point p1,point p2,point p3)
     21 {
     22     return ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y));
     23 }
     24 void interect(point x,point y,double a,double b,double c)//求2直线交点(xy与ax0+by0+c=0的交点)
     25 {
     26     double u=fabs(a*x.x+b*x.y+c);
     27     double v=fabs(a*y.x+b*y.y+c);
     28     q[++s].x=(x.x*v+y.x*u)/(u+v);
     29     q[s].y=(x.y*v+y.y*u)/(u+v);
     30 }
     31 void cut(double a,double b,double c)//半平面切割
     32 {
     33     s=0;
     34     int i;
     35     for(i=1;i<=m;i++)//枚举所有点
     36     {
     37         if(sig(a*p[i].x+b*p[i].y+c)>=0)//逆时针时为>=0
     38         {
     39             q[++s]=p[i];//符合
     40         }
     41         else
     42         {
     43             if(sig(a*p[i-1].x+b*p[i-1].y+c)>0)
     44                 interect(p[i-1],p[i],a,b,c);//p[i]p[i-1]与直线的交点符合
     45             if(sig(a*p[i+1].x+b*p[i+1].y+c)>0)
     46                 interect(p[i],p[i+1],a,b,c);//p[i]p[i+1]与直线的交点符合
     47         }
     48     }
     49     for(i=1;i<=s;i++)
     50     {
     51         p[i]=q[i];//更新
     52     }
     53     p[0]=p[s];
     54     p[s+1]=p[1];
     55     m=s;
     56 }
     57 int main()
     58 {
     59     //freopen("in.txt","r",stdin);
     60     int i,j;
     61     double mid;
     62     while(scanf("%d",&n)!=EOF&&n)
     63     {
     64         for(i=1;i<=n;i++)
     65         {
     66             scanf("%lf%lf",&input[i].x,&input[i].y);
     67             p[i]=input[i];
     68         }
     69         input[n+1]=input[1];
     70         p[0]=p[n];
     71         p[n+1]=p[1];
     72         double max=-1;
     73         for(i=1;i<=n;i++)
     74         {
     75             for(j=i+1;j<=n;j++)
     76             {
     77                 double temp=dis(p[i],p[j]);
     78                 if(max<temp)//找2点距离最大的点
     79                 {
     80                     max=temp;
     81                 }
     82             }
     83         }
     84         double l=0, r=max/2;
     85         while(r-l>eps)//二分半径
     86         {
     87             mid=(l+r)/2;
     88             double a,b,c;
     89             point tt,ta,tb;
     90             for(i=1;i<=n;i++)
     91             {
     92                 p[i]=input[i];
     93             }
     94             p[0]=p[n];
     95             p[n+1]=p[1];
     96             m=n;
     97             for(i=1;i<=n;i++)
     98             {
     99                 tt.x=input[i].y-input[i+1].y;//逆时针,注意顺序,每条边一起向“内”推进R
    100                 tt.y=input[i+1].x-input[i].x;
    101                 double k=mid/sqrt(tt.x*tt.x+tt.y*tt.y);
    102                 tt.x=tt.x*k;
    103                 tt.y=tt.y*k;
    104                 ta.x=input[i].x+tt.x;
    105                 ta.y=input[i].y+tt.y;
    106                 tb.x=input[i+1].x+tt.x;
    107                 tb.y=input[i+1].y+tt.y;
    108                 
    109                 a=ta.y-tb.y;//由2点求出直线ax+by+c=0
    110                 b=tb.x-ta.x;
    111                 c=ta.x*tb.y-ta.y*tb.x;
    112                 cut(a,b,c);
    113             }
    114             if(m<=2) r=mid;
    115             // else if(fabs(xmule(p[1],p[2],p[3]))<eps) r=mid;
    116             else l=mid;
    117         }
    118         printf("%.6lf\n",l);
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    再次或多次格式化导致namenode的ClusterID和datanode的ClusterID之间不一致的问题解决办法
    Linux安装aria2
    POJ 3335 Rotating Scoreboard 半平面交
    hdu 1540 Tunnel Warfare 线段树 区间合并
    hdu 3397 Sequence operation 线段树 区间更新 区间合并
    hud 3308 LCIS 线段树 区间合并
    POJ 3667 Hotel 线段树 区间合并
    POJ 2528 Mayor's posters 贴海报 线段树 区间更新
    POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化
    POJ 3468 A Simple Problem with Integers 线段树成段更新
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740211.html
Copyright © 2011-2022 走看看