題目如下:
Scrambled Polygon
簡單來說題意就是:
亂序給出凸多邊形的頂點座標,要求按逆時 針順序輸出各頂點。給的第一個點一定是 (0,0),沒有其他點在座標軸上,沒有三點 共線的情況。
Sample Input
0 0
70 -50
60 30
-30 -50
80 20
50 -60
90 -20
-30 -40
-10 -60
90 10
Sample Output
(0,0)
(-30,-40)
(-30,-50)
(-10,-60)
(50,-60)
(70,-50)
(90,-20)
(90,10)
(80,20)
(60,30)
Source
Rocky Mountain 2004
這道題主要運用的是叉積排序,我們首先來寫一下叉積排序吧
首先講到的是矢量的叉積,我們對於矢量的叉積的應用很多,簡單說幾點,比如三角形面積的應用我們可以用到,還有可以判斷是順時針還是逆時針,還可以判斷是否在半球面上。
關於判斷是順時針還是逆時針,我們可以用來判斷點和線段的關係與線段和線段之間的關係
當叉積大於0的時候,在順時針上,小於0時,在逆時針上,等於0的時候,那麼就共線.
叉積排序屬於極角排序的內容,關於極角排序,我們主要有以下幾種方法:
1.利用atan2()函數按極角從小到大排序;
2.利用叉積按極角從小到大排序;
3.先把象限從小到大排序,再利用極角從小到大排序;
但是2方法的精度較高,所以我們一般使用它;
代碼如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
const int maxn=75;
using namespace std;
struct vec{
double x,y;
vec(int xx,int yy):x(xx),y(yy) {}
vec(){}
double operator ^ (const vec & v) const{
return x*v.y-y*v.x;
}
};
#define point vec
point f[maxn];
vec operator - (const point &ta,const point &tb)
{
return vec(ta.x-tb.x,ta.y-tb.y);
}
bool operator < (const point &ta,const point &tb)
{
if((vec(tb-point(0,0))^vec(ta-point(0,0)))>0)
return true;
return false;
}
int main()
{
int x,y,n=0;
while(cin>>f[n].x>>f[n].y)
++n;
sort(f+1,f+n);
cout<<"(0,0)"<<endl;
for(int i=n-1;i>0;i--)
{
cout<<"("<<f[i].x<<","<<f[i].y<<")"<<endl;
}
return 0;
}
當然了我們寫模板的話,我們也可以用下面的這種方式來寫:
struct point {
double x,y;
};
double cha(double a,double b,double ta,double tb)
{
return (a*tb-ta*b);
}
double judge(point a,point b,point c)
{
return cha((b.x-a.x),(b.y-a.y),(c.x-a.x),(c.y-a.y));
}
bool jud(point a,point b)
{
point c;
c.x=0;
c.y=0;
if((judge(c,a,b))==0)
return a.x<b.x;
else return judge(c,a,b)>0;
}