1. 程式人生 > 其它 >[python]tkinter簡易的圖片瀏覽器

[python]tkinter簡易的圖片瀏覽器

極角

極角,指的就是以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;
}

原文