L3-021 神壇 (30 分)


在古老的邁瑞城,巍然屹立着 n 塊神石。長老們商議,選取 3 塊神石圍成一個神壇。因為神壇的能量強度與它的面積成反比,因此神壇的面積越小越好。特殊地,如果有兩塊神石坐標相同,或者三塊神石共線,神壇的面積為 0.000

長老們發現這個問題沒有那么簡單,於是委托你編程解決這個難題。

輸入格式:

輸入在第一行給出一個正整數 n(3 ≤ n ≤ 5000)。隨后 n 行,每行有兩個整數,分別表示神石的橫坐標、縱坐標(− 橫坐標、縱坐標 <)。

輸出格式:

在一行中輸出神壇的最小面積,四舍五入保留 3 位小數。

輸入樣例:

8
3 4
2 4
1 1
4 1
0 3
3 0
1 3
4 2

輸出樣例:

0.500

樣例解釋

輸出的數值等於圖中紅色或紫色框線的三角形的面積。

altar.JPG

 

暴力解只能對三個測試點,網上查的別人的解法,先按照極角排序,極角就是在極坐標下任意一點M和極點O連線的向量OM和x軸OX的夾角,對於兩個含同點向量按照極角排序,按照叉乘積,如果向量1叉乘向量2結果為正,表示向量2在向量1的左邊,為0表示共線,否則相反。

已知兩共起點向量,求組成三角形面積就是叉乘積取絕對值再乘0.5,因為三角形計算面積有個公式0.5absint。

至於為啥要按照極角排序,應該是省去一些不必要的情況,排好序,只需要相鄰倆向量求面積更新最小值即可。

代碼:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define inf 1e18
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pa;
int n;
pa point[5000];
pa line[5000];
double mp[5000][5000];
double ans = inf;
bool cmp(pa a,pa b) {
    if(a.first * b.second == b.first * a.second) return a.first < b.first;
    return a.first * b.second > b.first * a.second;
}
int main() {
    scanf("%d",&n);
    for(int i = 0;i < n;i ++) {
        scanf("%lld%lld",&point[i].first,&point[i].second);
    }
    for(int i = 0;i < n;i ++) {
        int t = 0;
        for(int j = 0;j < n;j ++) {
            if(i == j) continue;
            line[t ++] = pa(point[j].first - point[i].first,point[j].second - point[i].second);
        }
        sort(line,line + t,cmp);
        for(int j = 1;j < t;j ++) {
            ans = min(ans,0.5 * abs(line[j - 1].first * line[j].second - line[j - 1].second * line[j].first));
        }
    }
    printf("%.3f",ans);
}

極角排序:https://www.cnblogs.com/aiguona/p/7248311.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM