半平面交的学习戳这里:http://blog.csdn.net/accry/article/details/6070621
然而这题是要二分长度r……用每条直线的距离为r的平行线来截“凸包”
做平行线的方法是:对于向量(x,y),与它垂直的向量有:(y,-x)和(-y,x),然后再转化成单位向量,再乘以 r ,就得到了转移向量tmp,设直线上两点为A(x1,y1),B(x2,y2),用这个方法就找到了直线AB的平行线CD,其中C=A+tmp,D=b+tmp;
然而我傻逼的搞错了方向……结果平行线做成了远离凸包的那一条……导致答案一直增大QAQ
剩下的就没啥了,看是否存在这么一块半平面的交即可。
1 Source Code 2 Problem: 3525 User: sdfzyhy 3 Memory: 672K Time: 16MS 4 Language: G++ Result: Accepted 5 6 Source Code 7 8 //POJ 3525 9 #include<cmath> 10 #include<cstdio> 11 #include<cstring> 12 #include<cstdlib> 13 #include<iostream> 14 #include<algorithm> 15 #define rep(i,n) for(int i=0;i<n;++i) 16 #define F(i,j,n) for(int i=j;i<=n;++i) 17 #define D(i,j,n) for(int i=j;i>=n;--i) 18 using namespace std; 19 typedef long long LL; 20 inline int getint(){ 21 int r=1,v=0; char ch=getchar(); 22 for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1; 23 for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0'; 24 return r*v; 25 } 26 const int N=110; 27 const double eps=1e-6,INF=1e8; 28 /*******************template********************/ 29 30 31 int n; 32 struct Poi{ 33 double x,y; 34 Poi(){} 35 Poi(double x,double y):x(x),y(y){} 36 void read(){scanf("%lf%lf",&x,&y);} 37 void out(){printf("%f %f\n",x,y);} 38 }p[N],tp[N],s[N],o; 39 typedef Poi Vec; 40 Vec operator - (const Poi &a,const Poi &b){return Vec(a.x-b.x,a.y-b.y);} 41 Vec operator + (const Poi &a,const Vec &b){return Poi(a.x+b.x,a.y+b.y);} 42 Vec operator * (const double &k,const Vec a){return Vec(a.x*k,a.y*k);} 43 inline double Cross(const Vec &a,const Vec &b){return a.x*b.y-a.y*b.x;} 44 inline double Dot(const Vec &a,const Vec &b){return a.x*b.x+a.y*b.y;} 45 inline double Len(const Vec &a){return sqrt(Dot(a,a));} 46 inline int dcmp(double x){return x > eps ? 1 : x < eps ? -1 : 0;} 47 double getarea(Poi *a,int n){ 48 double ans=0.0; 49 F(i,1,n) ans+=Cross(a[i]-o,a[i+1]-o); 50 return ans*0.5; 51 } 52 Poi getpoint (const Poi &a,const Poi &b,const Poi &c,const Poi &d){ 53 Poi ans,tmp=b-a; 54 double k1=Cross(d-a,c-a),k2=Cross(c-b,d-b); 55 ans=a+(k1/(k1+k2))*tmp; 56 return ans; 57 } 58 inline void get_parallel(Poi &a,Poi &b,double r,Poi &c,Poi &d){ 59 // Poi tmp(b.y-a.y,a.x-b.x); 60 Poi tmp(a.y-b.y,b.x-a.x); 61 tmp=(r/Len(tmp))*tmp; 62 c=a+tmp; d=b+tmp; 63 // a.out(); b.out(); c.out(); d.out(); 64 // puts(""); 65 } 66 void init(){ 67 F(i,1,n) p[i].read(); 68 p[n+1]=p[1]; 69 } 70 bool check(double r){ 71 tp[1]=tp[5]=Poi(-INF,-INF); 72 tp[2]=Poi(INF,-INF); 73 tp[3]=Poi(INF,INF); 74 tp[4]=Poi(-INF,INF); 75 int num=4,size=0; 76 F(i,1,n){ 77 size=0; 78 F(j,1,num){ 79 Poi t1(0,0),t2(0,0); 80 get_parallel(p[i],p[i+1],r,t1,t2); 81 if (dcmp(Cross(t2-t1,tp[j]-t1))>=0) 82 s[++size]=tp[j]; 83 if (dcmp(Cross(t2-t1,tp[j]-t1)*Cross(t2-t1,tp[j+1]-t1))<0) 84 s[++size]=getpoint(t1,t2,tp[j],tp[j+1]); 85 } 86 s[size+1]=s[1]; 87 F(j,1,size+1) tp[j]=s[j]; 88 num=size; 89 // printf("num=%d\n",num); 90 // F(j,1,num) tp[j].out(); 91 } 92 // printf("n=%d num=%d size=%d\n",n,num,size); 93 if (num>0) return 1; 94 else return 0; 95 } 96 int main(){ 97 #ifndef ONLINE_JUDGE 98 freopen("3525.in","r",stdin); 99 freopen("3525.out","w",stdout); 100 #endif 101 while(scanf("%d",&n)!=EOF && n){ 102 init(); 103 double l=0.0,r=1e7,mid; 104 while(r-l>eps){ 105 mid=(l+r)/2; 106 // printf("mid=%f\n",mid); 107 if (check(mid)) l=mid; 108 else r=mid; 109 } 110 printf("%f\n",l); 111 } 112 return 0; 113 }