[python]tkinter簡易的圖片瀏覽器
阿新 • • 發佈:2022-04-04
極角
極角,指的就是以x軸正半軸為始邊,逆時針轉過的角,這個角的範圍是[0,2π]。
極角排序就是按極角大小排序...
極角排序求法
利用atan2函式
atan2(y,x),表示(x,y)這個點與原點連線,這條線與x軸正半軸的夾角,這裡的這個極角的範圍是[−π,π]的,一二象限為正,三四象限為負。所以我們從小到大排完序後,實際上是第三象限→第四象限→第一象限→第二象限。
struct node{ int x,y; double angle; inline bool operator < (const node &t) const{ return angle<t.angle; } } for (int i=1;i<=n;i++){ read(a[i].x),read(a[i].y); a[i].angle=atan2(a[i].y,a[i].x); } sort(a+1,a+n+1,cmp);
利用叉積來進行排序
叉積
已知兩點座標,通過叉積可以求得與原點所圍成的三角形的有向面積。
比如這兩個點為a,b.
\(\frac{1}{2}*(a.x*b.y-a.y*b.x)\) 即為該三角形面積,那麼為什麼說是有向面積呢,如果這個值是正的,說明b位於a的正方向,即逆時針方向(當然,這個角度小於π),反之,如果這個面積是負的,說明b位於a的負方向,即順時針方向。
那麼我們就可以通過叉積來求極角了
struct node{ int x,y; double angle; inline int operator * (const node &t) const{ return a.x*b.y-a.y*b.x; } } inline bool cmp(node a,node b){ return a*b>0; } for (int i=1;i<=n;i++){ read(a[i].x),read(a[i].y); } sort(a+1,a+n+1,cmp);
比較兩種求法的優劣
第一種求法的常數比較優秀,但是精度有一定的損失。而叉積的求法常數較大,但是沒有精度損失,可以根據情況的不同進行選擇。
例題
L3-3 神壇 (30 分)
點選檢視題目
在古老的邁瑞城,巍然屹立著 n 塊神石。長老們商議,選取 3 塊神石圍成一個神壇。因為神壇的能量強度與它的面積成反比,因此神壇的面積越小越好。特殊地,如果有兩塊神石座標相同,或者三塊神石共線,神壇的面積為 0.000。
長老們發現這個問題沒有那麼簡單,於是委託你程式設計解決這個難題。
輸入格式:
輸入在第一行給出一個正整數 n(3 ≤ n ≤ 5000)。隨後 n 行,每行有兩個整數,分別表示神石的橫座標、縱座標(−10
9
≤ 橫座標、縱座標 <10
9
)。
輸出格式:
在一行中輸出神壇的最小面積,四捨五入保留 3 位小數。
輸入樣例:
8
3 4
2 4
1 1
4 1
0 3
3 0
1 3
4 2
輸出樣例:
0.500
程式碼
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node{
ll x,y;
int rel;
}a[5010],b[5010];
int n;
bool cmp(node x,node y){ //極角排序
if( x.rel != y.rel)
return x.rel < y.rel;
return x.x*y.y-x.y*y.x>0;
}
int judge(node x) { //返回象限
if(x.x > 0 && x.y > 0) return 1;
if(x.x > 0 && x.y < 0) return 2;
if(x.x < 0 && x.y < 0) return 3;
if(x.x < 0 && x.y > 0) return 4;
}
int main(){
scanf("%d",&n);
for( int i=1;i<=n;i++)
scanf("%lld%lld",&a[i].x,&a[i].y);
double ans=-1;
int cnt;
for(int i=1;i<=n;i++){
cnt=1;
for(int j=1;j<=n;j++){
if( i==j )
continue;
b[cnt].x = a[j].x-a[i].x;
b[cnt].y = a[j].y-a[i].y;
b[cnt].rel = judge(b[cnt]);
cnt++;
}
sort(b+1,b+n,cmp);
for(int j=1;j<n-1;j++){
if( ans==-1||fabs(b[j+1].x*b[j].y-b[j+1].y*b[j].x)*0.5<ans )
ans=fabs(b[j+1].x*b[j].y-b[j+1].y*b[j].x)*0.5;
}
}
printf("%.3f\n",ans);
return 0;
}