已知三個點 p0,p1,p2 的叉積函數 cross:
double cross(point p0,point p1,point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y) ;
}
叉積的一個重要性質,判斷兩向量互相之間的順逆時針關係。
若 P×Q>0,則 P 在 Q 的順時針方向;
若 P×Q<0,則 P 在 Q 的逆時針方向;
若 P×Q=0,則 P 和 Q 共線,但可能同向也可能反向;
注:Distance 函數名字可以換掉,但是不能換成 distance 會編譯出錯,原因是 distance 是 stl 中 計算距離的函數.按道理會自動選用我們自己定義的,但是不明白為什麼報錯,總之是會報錯了;
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;#define maxn 50+3struct point{ int x; int y; int no;};point P[maxn+3],res[maxn];int pos; //全域變數,記錄當前的 基準點int cross(const point &p0, const point &p1, const point &p2) //計算叉積{ return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);}int Distance(const point &a, const point &b) //兩向量間的距離{ return (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y);}bool cmp(const point & p1,const point & p2) //sort 的比較函數. 極角排序函數{ int ans = cross(P[pos],p1,p2); //計算叉積 if(ans > 0) //叉積>0 則以 p[pos] 位置為基準 p1 在 p2 的順時針方向 return true; else if(ans == 0 && Distance(P[pos],p1)<Distance(P[pos],p2)) //叉積=0 三點共線, 距離短的在前面 return true; return false;}void swap(point &a, point &b) //交換函數{ point temp = a; a = b; b = temp;}int main(){#ifndef ONLINE_JUDGE freopen("in","r",stdin);#endif int M,N; cin>>M; while(M--) { cin>>N; for(int i = 1; i <= N; i++) { cin>>P[i].no>>P[i].x>>P[i].y; if(P[i].y < P[1].y) swap(P[i],P[1]); } pos = 1; sort(P+pos+1,P+N+1,cmp); res[pos++] = P[pos]; for(int i = 2; i <= N; i++) { sort(P+pos+1,P+N+1,cmp); res[pos++] = P[pos]; } cout<<pos-1; for(int i = 1; i <= N; i++) { cout<<" "<<res[i].no; } cout<<endl; }}