POJ 3525 半平面交

2021-05-24 21:52:58 字數 3393 閱讀 4374

題意:

求凸包內切圓最大半徑

題解:二分半徑,將凸包所有邊往凸包內平移這麼半徑長度,看平移後是否能圍成凸包.

* 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...