HDU1348--Wall(凸包)

佷裸的一道凸包題,就是多組數據,每組給你點數和圓的半徑,而後一堆座標,最後輸出圓的周長加上這個最小凸包的周長。spa

這裏我用的是Graham_scan方法,具體的就是:code

1.咱們取Y座標最小的點A做爲原點創建平面直角座標系,而後以剩餘點與X軸的夾角從小到大逆時針依次標記,能夠不難發現A,B必在這個最小凸包上blog

 

2.而後按照字母順序鏈接,首先鏈接AB,而後是BC,咱們發現∠ABC是小於180°的,因此咱們暫且認爲C是在這個最小凸包上的排序

 

3.如今,咱們繼續鏈接CD,但此時GG的事就是咱們發現∠BCD爲大約180°的角若是咱們認爲D也是凸包上的點,這裏就會出現一個凹陷,所以咱們既要保證C、D都在凸包內,又要不出現凹陷,只能去掉BC而選BDit

4.以此類推,不難發現咱們的最小凸包應該長這個樣子io

 

5.最後,用兩點距離公式來求出周長便可class

Q:如何判斷夾角是否爲凸凹?方法

咱們用叉乘來判斷im

 

 這裏的左邊即爲小於180°,右邊爲大於180°(能夠畫圖證實)數據

這樣就能夠判斷了。

醜陋的代碼(這道題別忘加上2πr):

#include<cstdio> #include<cmath> #include<algorithm>
using namespace std; const int  maxn=1010; const double Pi=acos(-1.0); struct Node { double x,y; }p[maxn],P[maxn]; int n,tot; double ans,l; double X(Node A,Node B,Node C) { return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y); }//叉乘 
double len(Node A ,Node B) { return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); }//距離 
bool cmp(Node A,Node B) { double pp=X(p[0],A,B); if(pp>0) return true; if(pp<0) return false; return len(p[0],A)<len(p[0],B); }//按夾角逆時針排序 
int main() { int t; scanf("%d",&t); for(int u=1;u<=t;u++) { if(u!=1)printf("\n"); scanf("%d%lf",&n,&l); ans=2*Pi*l; for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(n==1) { printf("%.0f\n",ans); } else if(n==2) { printf("%.0f\n",ans+len(p[0],p[1])); } else { for(int i=0;i<n;i++) { if(p[i].y<p[0].y) { swap(p[i],p[0]); } else if(p[i].y==p[0].y&&p[i].x<p[0].x) { swap(p[i],p[0]); } } sort(p+1,p+n,cmp); P[0]=p[0]; P[1]=p[1]; tot=1; for(int i=2;i<n;i++) { while(tot>0&&X(P[tot-1],P[tot],p[i])<=0) tot--; tot++; P[tot]=p[i]; } for(int i=0;i<tot;i++) ans+=len(P[i],P[i+1]); ans+=len(P[0],P[tot]); printf("%.0f\n",ans); } } return 0; } 

感受說的應該是不太好,有什麼錯誤請指出,謝謝

相關文章
相關標籤/搜索