题目链接

题意 : 让你找出最小的凸包周长 。

思路 : 用Graham求出凸包,然后对每条边求长即可。

Graham详解

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <math.h>
 5 #include <algorithm>
 6 
 7 using namespace std ;
 8 
 9 struct point
10 {
11     int x,y ;
12 }p[110],p1[110];
13 int n ;
14 
15 double dis(point a,point b)
16 {
17     return sqrt(double((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))) ;
18 }
19 double cross(point a,point b,point c)
20 {
21     return (a.x-c.x)*(b.y-c.y) - (a.y-c.y)*(b.x-c.x) ;
22 }
23 bool cmp(point a,point b)
24 {
25     if(cross(a,b,p[0]) > 0 || cross(a,b,p[0]) == 0 && dis(a,p[0]) < dis(b,p[0]))
26         return true ;
27     return false ;
28 }
29 void Graham()
30 {
31     int cnt;
32     sort(p+1,p+n,cmp) ;
33     p[n] = p[0] ;
34     p1[0] = p[0] ;
35     p1[1] = p[1] ;
36     cnt = 1 ;
37     for(int i = 2 ; i <= n ; i++)
38     {
39         while(cnt >= 1 && cross(p1[cnt-1],p1[cnt],p[i]) <= 0) cnt -- ;
40         p1[ ++cnt] = p[i] ;
41     }
42     double sum = 0.0 ;
43     for(int i = 0 ; i < cnt ; i++)
44         {
45             sum += dis(p1[i],p1[i+1]) ;
46             //printf("*%.2lf*\n",sum) ;
47         }
48         printf("%.2lf\n",sum) ;
49 }
50 int main()
51 {
52     while(~scanf("%d",&n) && n)
53     {
54         int pos = 0 ;
55         for(int i = 0 ; i < n ; i++)
56         {
57             scanf("%d %d",&p[i].x,&p[i].y) ;
58             if(p[pos].y > p[i].y || (p[pos].y == p[i].y && p[i].x < p[pos].x))
59                 pos = i ;
60         }
61         if(n == 1) {puts("0.00");continue ;}
62         if(n == 2)
63         {
64             printf("%.2lf\n",dis(p[1],p[0])) ;
65             continue ;
66         }
67         swap(p[pos],p[0]) ;
68         //printf("%d %d\n",p[0].x,p[0].y) ;
69         Graham() ;
70     }
71     return 0 ;
72 }
View Code

 

posted on 2014-08-29 09:34  枫、  阅读(167)  评论(0编辑  收藏  举报