poj 3384 Feng Shui 半平面交

给定一个多边形,在多边形内放有两个相同的圆,使两个圆尽可能多的覆盖多边形。输出最终两个圆心的位置。
最优的放置方法必定是圆内切于两条边,那么把所有的边向内推移半径R的距离,得到新的多边形(也有可能是一个点或一条直线),求出新多边形相距最远的两个顶点,这两个顶点就是圆心的位置了。
 
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<iostream>
  4 #include<cmath>
  5 using namespace std;
  6 const double pi=acos(-1.0);
  7 const int N=105;
  8 const double eps=1e-9;
  9 int n,m,s;
 10 struct point
 11 {
 12     double x,y;
 13 }p[N],q[N],input[N];
 14 int sig(double k)
 15 {
 16     return (k<-eps)?-1:(k>eps);
 17 }
 18 double dis(point a,point b)
 19 {
 20     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 21 }
 22 double xmule(point p1,point p2,point p3)
 23 {
 24     return ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y));
 25 }
 26 void interect(point x,point y,double a,double b,double c)//求2直线交点(xy与ax0+by0+c=0的交点)
 27 {
 28     double u=fabs(a*x.x+b*x.y+c);
 29     double v=fabs(a*y.x+b*y.y+c);
 30     q[++s].x=(x.x*v+y.x*u)/(u+v);
 31     q[s].y=(x.y*v+y.y*u)/(u+v);
 32 }
 33 void cut(double a,double b,double c)//半平面切割
 34 {
 35     s=0;
 36     int i;
 37     for(i=1;i<=m;i++)//枚举所有点
 38     {
 39         if(sig(a*p[i].x+b*p[i].y+c)<=0)
 40         {
 41             q[++s]=p[i];//符合
 42         }
 43         else
 44         {
 45             if(sig(a*p[i-1].x+b*p[i-1].y+c)<0)
 46                 interect(p[i-1],p[i],a,b,c);//p[i]p[i-1]与直线的交点符合
 47             if(sig(a*p[i+1].x+b*p[i+1].y+c)<0)
 48                 interect(p[i],p[i+1],a,b,c);//p[i]p[i+1]与直线的交点符合
 49         }
 50     }
 51     for(i=1;i<=s;i++)
 52     {
 53         p[i]=q[i];//更新
 54     }
 55     p[0]=p[s];
 56     p[s+1]=p[1];
 57     m=s;
 58 }
 59 double dir(point a,point b)
 60 {
 61     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 62 }
 63 int main()
 64 {
 65     int i,j,ans1,ans2,r;
 66     double mid,max,len;
 67     while(scanf("%d%d",&n,&r)!=EOF)
 68     {
 69         for(i=1;i<=n;i++)
 70         {
 71             scanf("%lf%lf",&input[i].x,&input[i].y);
 72             p[i]=input[i];
 73         }
 74         input[n+1]=input[1];
 75         p[0]=p[n];
 76         p[n+1]=p[1];
 77         double a,b,c;
 78         point tt,ta,tb;
 79         for(i=1;i<=n;i++)
 80         {
 81             p[i]=input[i];
 82         }
 83         p[0]=p[n];
 84         p[n+1]=p[1];
 85         m=n;
 86         for(i=1;i<=n;i++)
 87         {
 88             tt.x=input[i+1].y-input[i].y;//顺时针,注意顺序,每条边一起向“内”推进R
 89             tt.y=input[i].x-input[i+1].x;
 90             double k=r*1.0/sqrt(tt.x*tt.x+tt.y*tt.y);
 91             tt.x=tt.x*k;
 92             tt.y=tt.y*k;
 93             ta.x=input[i].x+tt.x;
 94             ta.y=input[i].y+tt.y;
 95             tb.x=input[i+1].x+tt.x;
 96             tb.y=input[i+1].y+tt.y;
 97             
 98             a=ta.y-tb.y;//由2点求出直线ax+by+c=0
 99             b=tb.x-ta.x;
100             c=ta.x*tb.y-ta.y*tb.x;
101             cut(a,b,c);
102         }
103         max=-1;
104         ans1=m;
105         ans2=m;
106         for(i=1;i<m;i++)
107             for(j=i+1;j<=m;j++)
108             {
109                 len=dir(p[i],p[j]);
110                 if(len-max>eps)
111                 {
112                     max=len;
113                     ans1=i;
114                     ans2=j;
115                 }
116             }
117             printf("%.4f %.4f %.4f %.4f\n",p[ans1].x,p[ans1].y,p[ans2].x,p[ans2].y);
118     }
119     return 0;
120 }

 

 



posted @ 2011-05-07 23:58  CoderZhuang  阅读(208)  评论(0编辑  收藏  举报