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 }

 

你可能感兴趣的:(ant)