題意:
求凸包內切圓最大半徑
題解:二分半徑,將凸包所有邊往凸包內平移這麼半徑長度,看平移後是否能圍成凸包.
* file: main.cpp
* author: swordholy
* created on 2023年3月25日, 下午7:56
//求凸包內切圓最大半徑
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 110
#define eps 1e-10
#define zero(x) (((x)>0?(x):-(x))struct pt
double x,y;
pt()
pt(double xx,double yy)
x=xx;
y=yy;
double dist(pt p1,pt p2)
return sqrt(1.0*(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
double cross(pt a,pt b)
return a.x*b.y-a.y*b.x;
double cross(pt a,pt b,pt c)
return cross(pt(a.x-c.x,a.y-c.y),pt(b.x-c.x,b.y-c.y));
double same_side(pt p1,pt p2,pt l1,pt l2)
return cross(l1,p1,l2)*cross(l1,p2,l2)>eps;
struct convex
int n;
pt p[maxn];
struct plane//半平面,a,b構成直線,side表示在哪個面
pt a,b,side;
ret.x-u1.x=t(u2.x-u1.x)
ret.y-u1.y=t(u2.y-u1.y)
ret.x-v1.x=tt(v2.x-v1.x)
ret.y-v1.y=tt(v2.y-v1.y)
解以上方程可得線段交點ret
pt intersection(pt u1,pt u2,pt v1,pt v2)
pt ret=u1;
double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
return ret;
convex src,ans;
convex half_plane(convex c,plane pl)//半平面交,一條直線切割凸包
int i,j;
double r1,r2;
convex ans,ans1;
ans.n=0;
for(i=0;iif (same_side(c.p[i],pl.side,pl.a,pl.b))
ans.p[ans.n++]=c.p[i];
if ((!same_side(c.p[i],c.p[(i+1)%c.n],pl.a,pl.b))&&(!(zero(cross(c.p[i],pl.a,pl.b))&&zero(cross(c.p[(i+1)%c.n],pl.a,pl.b)))))
ans.p[ans.n++]=intersection(c.p[i],c.p[(i+1)%c.n],pl.a,pl.b);//有點在直線上的話該點會被加入兩次
ans1.n=0;
for(i=0;iif (!i||!zero(ans.p[i].x-ans.p[i-1].x)||!zero(ans.p[i].y-ans.p[i-1].y))
ans1.p[ans1.n++]=ans.p[i];//過濾重複點
if (zero(ans1.p[ans1.n-1].x-ans1.p[0].x)&&zero(ans1.p[ans1.n-1].y-ans1.p[0].y))
ans1.n--;
if (ans1.n<3)
ans1.n=0;
return ans1;
bool judge(double x)
convex ans;
pt tt,ta,tb;
ans=src;
for (int i = 0; i < src.n; i++)
tt.x = src.p[i].y - src.p[i+1].y;
tt.y = src.p[i + 1].x - src.p[i].x;
double k = x / sqrt(tt.x * tt.x + tt.y * tt.y);
tt.x = tt.x*k;
tt.y = tt.y*k;
ta.x = src.p[i].x + tt.x;
ta.y = src.p[i].y + tt.y;
tb.x = src.p[i + 1].x + tt.x;
tb.y = src.p[i + 1].y + tt.y;
plane pl;
pl.a=ta;pl.b=tb;
pl.side.x = src.p[i].x + tt.x + tt.x;
pl.side.y = src.p[i].y + tt.y + tt.y;
ans=half_plane(ans,pl);
if (ans.n==0) return false;
return true;
int main(int argc, char** argv)
int n,i,j,tcase;
double maxl;
while(scanf("%d",&n)!=eof)
src.n=n;
for(i=0;iscanf("%lf %lf",&src.p[i].x,&src.p[i].y);
src.p[n]=src.p[0];
double d,maxd=0;
for(i=0;ifor(j=0;jif ((d=dist(src.p[i],src.p[j]))>maxd)
maxd=d;
double l,r,mid,k,ansd;
l=0;r=maxd/2;
ansd=0;
while(l+epsmid=(l+r)/2;
if ( judge(mid) )
ansd=mid;
l=mid+eps;
else
r=mid-eps;
printf("%.6lf/n",ansd);
return 0;
POJ 1755 Triathlon 半平面交
看的這裡 題意 鐵人三項比賽,給出 個人進行每一項的速度vi,ui,wi 對每個人判斷,通過改變3項比賽的路程,是否能讓該人獲勝 嚴格獲勝 思路 題目實際上是給出了n個式子方程,ti ai x bi y ci z 0 i n 要判斷第i個人能否獲勝,即判斷不等式組 tj ti 0,0 j n j i...
POJ 3384 Feng Shui 半平面交
題目給出兩個圓和乙個多邊形 問是否能讓兩個圓在多邊形內。並且覆蓋的面積最大 圓的半徑為r,我們則讓多邊形的每條邊都往內部退r距離。然後求半平面交得出的點集中,最遠的兩個點則是兩圓的圓心即可 include include include include include include include...
半平面交 POJ 3384 Feng Shui
先把每條邊壓縮r的距離,求出半平面交,然後半平面交的最遠點對就是答案了。要注意最後的點數只有乙個時的情況,此時兩個圓重合。但是半平面交求出的平面是不含直線上的點,所以這時半平面交求出的點集為空。我的處理方法是壓縮每一條邊的時候少壓縮一點距離,這樣子求出的點不會是空集,注意把握好精度就可以了。incl...