多边形内最大半径圆。
哇没有枉费了我自闭了这么些天,大概五天前我看到这种题可能毫无思路抓耳挠腮举手投降什么的,现在已经能1A了哇。
还是先玩一会计算几何,刷个几百道
嗯这个半平面交+二分就阔以解决。虽然队友说他施展三分套三分*****
想象一下,如果一个多边形能放进去半径为r的圆,那么在每条边向里平移r之后,他的内核一定不为空。
所以我们可以二分r,然后求半平面交,平移操作其实很好处理。
1A了很开森,去快乐的玩耍惹。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <vector> 5 #include <cmath> 6 #include <deque> 7 using namespace std; 8 typedef double db; 9 const db eps=1e-6; 10 const db pi=acos(-1); 11 int sign(db k){ 12 if (k>eps) return 1; else if (k<-eps) return -1; return 0; 13 } 14 int cmp(db k1,db k2){return sign(k1-k2);} 15 struct point{ 16 db x,y; 17 point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} 18 point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} 19 point operator * (db k1) const{return (point){x*k1,y*k1};} 20 point operator / (db k1) const{return (point){x/k1,y/k1};} 21 db abs(){return sqrt(x*x+y*y);} 22 point unit(){db w=abs(); return point{x/w,y/w};} 23 point turn90(){ return point{-y,x};} 24 db getP()const { return sign(y)==1||(sign(y)==0&&sign(x)==-1);} 25 }; 26 db cross(point k1,point k2){ return k1.x*k2.y-k1.y*k2.x;} 27 db dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;} 28 db rad(point k1,point k2){ return atan2(cross(k1,k2),dot(k1,k2));} 29 int compareangle(point k1,point k2){ 30 return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&sign(cross(k1,k2))>0); 31 } 32 point getLL(point k1,point k2,point k3,point k4){ 33 db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3); 34 return (k1*w2+k2*w1)/(w1+w2); 35 } 36 struct line{ 37 point p[2]; 38 line(point k1,point k2){p[0]=k1;p[1]=k2;} 39 point &operator[](int k){ return p[k];} 40 int include(point k){ return sign(cross(p[1]-p[0],k-p[0])>0);} 41 point dir(){ return p[1]-p[0];} 42 line push(db eps){//向左手边平移eps 43 //const db eps=1e-6; 44 point delta=(p[1]-p[0]).turn90().unit()*eps; 45 return {p[0]-delta,p[1]-delta}; 46 } 47 }; 48 point getLL(line k1,line k2){ 49 return getLL(k1[0],k1[1],k2[0],k2[1]); 50 } 51 int parallel(line k1,line k2){ return sign(cross(k1.dir(),k2.dir()))==0;} 52 int sameDir(line k1,line k2){ 53 return parallel(k1,k2)&&sign(dot(k1.dir(),k2.dir()))==1; 54 } 55 int operator <(line k1,line k2){ 56 if(sameDir(k1,k2))return k2.include(k1[0]); 57 return compareangle(k1.dir(),k2.dir()); 58 } 59 int checkpos(line k1,line k2,line k3){ return k3.include(getLL(k1,k2));} 60 vector<line> getHL(vector<line> &L){ 61 sort(L.begin(),L.end());deque<line> q; 62 for(int i=0;i<L.size();i++){ 63 if(i&&sameDir(L[i],L[i-1]))continue; 64 while (q.size()>1&&!checkpos(q[q.size()-2],q[q.size()-1],L[i]))q.pop_back(); 65 while (q.size()>1&&!checkpos(q[1],q[0],L[i]))q.pop_front(); 66 q.push_back(L[i]); 67 } 68 while (q.size()>2&&!checkpos(q[q.size()-2],q[q.size()-1],q[0]))q.pop_back(); 69 while (q.size()>2&&!checkpos(q[1],q[0],q[q.size()-1]))q.pop_front(); 70 vector<line> ans;for(int i=0;i<q.size();i++)ans.push_back(q[i]); 71 return ans; 72 } 73 point p[1551]; 74 int n; 75 bool cw(){//时针 76 db s=0; 77 for(int i=1;i<n-1;i++){ 78 s+=cross(p[i]-p[0],p[i+1]-p[0]); 79 } 80 return s>0; 81 } 82 vector<line> L,tmp; 83 bool check(db x){ 84 tmp.clear(); 85 for(int i=0;i<L.size();i++){ 86 tmp.push_back(L[i].push(-x)); 87 } 88 tmp = getHL(tmp); 89 if(tmp.size()>=3) 90 return true; 91 return false; 92 } 93 int main(){ 94 //freopen("3525.in","r",stdin); 95 while (scanf("%d",&n)&&n){ 96 for(int i=0;i<n;i++){ 97 scanf("%lf%lf",&p[i].x,&p[i].y); 98 } 99 if(!cw())reverse(p,p+n); 100 for(int i=0;i<n;i++){ 101 L.push_back(line(p[i],p[(i+1)%n])); 102 } 103 db l = 0,r=100000.0; 104 while (l+0.0000001<r){ 105 db mid = (l+r)/2; 106 if(check(mid)) 107 l=mid; 108 else 109 r=mid; 110 } 111 printf("%.7f\n",l); 112 L.clear(); 113 } 114 }