在古老的邁瑞城,巍然屹立着 n 塊神石。長老們商議,選取 3 塊神石圍成一個神壇。因為神壇的能量強度與它的面積成反比,因此神壇的面積越小越好。特殊地,如果有兩塊神石坐標相同,或者三塊神石共線,神壇的面積為
0.000
。
長老們發現這個問題沒有那么簡單,於是委托你編程解決這個難題。
輸入格式:
輸入在第一行給出一個正整數 n(3 ≤n≤5000)。隨后 n 行,每行有兩個整數,分別表示神石的橫坐標、縱坐標(-109≤橫坐標、縱坐標<109)。
輸出格式:
在一行中輸出神壇的最小面積,四舍五入保留 3 位小數。
輸入樣例:
8
3 4
2 4
1 1
4 1
0 3
3 0
1 3
4 2
輸出樣例:
0.500
樣例解釋
輸出的數值等於圖中紅色或紫色框線的三角形的面積。
題意
N個點求最小三角形。
題解
首先需要知道3個點如何求S,0.5*abs(aXb)。
枚舉每個點,極角排序,求出相鄰向量的面積取個最小。
通過畫圖,可以發現若不取相鄰,雖然也可以但是得多一層循環不能接受。
取相鄰,可以發現剛好覆蓋了所有最小的三角形。
代碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int N=5005; 5 6 int n; 7 struct point//存儲點 8 { 9 ll x,y; 10 }p[N],c[N]; 11 bool cmp(point a,point b)//按順時針排序 12 { 13 return b.y*a.x>b.x*a.y; 14 } 15 int main() 16 { 17 scanf("%d",&n); 18 for(int i=0;i<n;i++) 19 scanf("%lld%lld",&p[i].x,&p[i].y); 20 ll ans=1e18; 21 for(int i=0;i<n;i++) 22 { 23 int k=0; 24 for(int j=0;j<n;j++) 25 { 26 if(i!=j) 27 { 28 c[k].x=p[j].x-p[i].x; 29 c[k].y=p[j].y-p[i].y; 30 k++; 31 } 32 } 33 sort(c,c+k,cmp); 34 for(int j=1;j<k;j++) 35 ans=min(ans,abs(c[j].y*c[j-1].x-c[j].x*c[j-1].y)); 36 } 37 printf("%.3f\n",ans/2.); 38 return 0; 39 }