這題一上來首先想到的是能否用數學方法來求得這個點..比如說畫一個半徑最小的圓使其與所有線段相交或相切…那麼圓心就是所求..想法似乎沒問題..但怎麼來求是毫無頭緒~想了良久也沒想出用數學的方法如何?…
還是用枚舉了…題目範圍不大..並且精度要求不高..將整個( 0 , 0 ) ~ ( 100 ,100 ) 的連續空間離散分成1000個每個相距0.1的點..枚舉每個點..定能找到答案..複雜度是 N*O(100^2)…估計最大資料時間大概需要十秒..發現這個時間是可以有最佳化空間的…我就直接用二分了..每次枚舉9個點 ( 正方形平均的9個點 )…找到最有點後再以這個點為九個點的中心點縮小步長再嘗試9個點..直道枚舉的兩點間相差<0.01..也就是步長<0.01…
還有很重要的一個問題..枚舉了一個點如何求出其到某線段的最短距離?..要分兩種情況..第一種是這個點做垂線會落到這個線段上…這種情況用差乘求出這個點與線段構成的三角形面積*2…然後再除以這個線段的長度就是垂線的長度…而第二種情況是這個點對線段做出的垂線線上段外..那麼最短的距離只可能是到線段兩個端點距離的最短那個..如何判斷這兩種情況…其實出現第二種情況是因為這個點與線段構成的三角形是鈍角三角形..並且不是這個點的兩側是鈍角..是另外兩個角有一個是鈍角..如何判斷鈍角三角形..先求出三條邊的長度..都知道座標這個很好求…當x1^2+x2^2<x3^2…代表x1與x2的夾角是鈍角…
Program:
/* ID: zzyzzy12 LANG: C++ TASK: fence3*/ #include<iostream> #include<istream> #include<stdio.h> #include<string.h> #include<math.h> #include<stack>#include<map>#include<algorithm> #include<queue> #define oo 2000000005 #define ll long long #define pi (atan(2)+atan(0.5))*2 using namespace std;struct node{ double x0,y0,x1,y1,len; }line[152];int i,n;double x,y,ansx,ansy,ans,now,MaxX,MaxY,StartX,StartY,len,step; double dis(node a){ double x1,y1,x2,y2; x1=(x-a.x0)*(x-a.x0)+(y-a.y0)*(y-a.y0); x2=(x-a.x1)*(x-a.x1)+(y-a.y1)*(y-a.y1); if (x1-x2-a.len*a.len>-0.001 || x2-x1-a.len*a.len>-0.001) { if (x1<x2) return sqrt(x1); return sqrt(x2); } x1=x-a.x0; y1=y-a.y0; x2=a.x1-a.x0; y2=a.y1-a.y0; x1=x1*y2-x2*y1; if (x1<0) x1=-x1; return x1/a.len;}int main() { freopen("fence3.in","r",stdin); freopen("fence3.out","w",stdout); StartX=StartY=oo; MaxX=MaxY=-oo; scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&line[i].x0,&line[i].y0,&line[i].x1,&line[i].y1); line[i].len=sqrt((line[i].x0-line[i].x1)*(line[i].x0-line[i].x1)+(line[i].y0-line[i].y1)*(line[i].y0-line[i].y1)); if (line[i].x1<line[i].x0) { x=line[i].x1; line[i].x1=line[i].x0; line[i].x0=x; } if (line[i].y1<line[i].y0) { y=line[i].y1; line[i].y1=line[i].y0; line[i].y0=y; } if (line[i].x1>MaxX) MaxX=line[i].x1; if (line[i].x0<StartX) StartX=line[i].x0; if (line[i].y1>MaxY) MaxY=line[i].y1; if (line[i].y0<StartY) StartY=line[i].y0; } if (MaxY>MaxX) len=MaxY/2; else len=MaxX/2; ans=oo; ans*=ans; while (len>0.01) { step=len/4; MaxX=StartX+len; MaxY=StartY+len; for (x=StartX;x<=MaxX;x+=step) for (y=StartY;y<=MaxY;y+=step) { now=0; for (i=1;i<=n;i++) { now+=dis(line[i]); if (now>ans) break; } if (now<ans) { ans=now; ansx=x; ansy=y; } } StartX=ansx-step/2; StartY=ansy-step/2; len/=2; } printf("%.1lf %.1lf %.1lf\n",ansx,ansy,ans); return 0; }