http://acm.hdu.edu.cn/showproblem.php?pid=1392
题目大意:
二维平面给定n个点,用一条最短的绳子将所有的点都围在里面,求绳子的长度。
解题思路:
凸包的模板。凸包有很多的算法。这里用Adrew。
注意这几组测试数据
1
1 1
3
0 0
1 0
2 0
输出数据
0.00
2.00
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 6 #define MAXN 100+10 7 8 struct Point{ 9 double x, y; 10 11 Point(double x = 0, double y = 0): x(x), y(y){} 12 13 void scan(){ 14 scanf("%lf %lf", &x, &y); 15 } 16 }; 17 18 typedef Point Vector; 19 20 Vector operator - (Vector A, Vector B){ 21 return Vector(A.x - B.x, A.y - B.y); 22 } 23 24 double dot(Vector A, Vector B){//点乘 25 return A.x * B.x + A.y * B.y; 26 } 27 double length(Vector A){//向量模 28 return sqrt(dot(A, A)); 29 } 30 double cross(Vector A, Vector B){//叉乘 31 return A.x * B.y - A.y * B.x; 32 } 33 34 int n; 35 Point p[MAXN], stack[MAXN]; 36 37 bool input(){ 38 scanf("%d", &n); 39 if(n == 0) return false; 40 for(int i = 0; i < n; ++i){ 41 p[i].scan(); 42 } 43 return true; 44 } 45 46 bool cmp(Point A, Point B){ 47 return A.x < B.x || (A.x == B.x && A.y < B.y); 48 } 49 50 int convex_hull(){//Adrew算法 求凸包 51 sort(p, p + n, cmp); 52 53 int m = 0; 54 for(int i = 0; i < n; ++i){ 55 while(m > 1 && cross(stack[m - 1] - stack[m - 2], p[i] - stack[m - 2]) <= 0) --m; 56 stack[m ++] = p[i]; 57 } 58 int k = m; 59 for(int i = n - 1; i >= 0; --i){ 60 while(m > k && cross(stack[m - 1] - stack[m - 2], p[i] - stack[m - 2]) <= 0) --m; 61 stack[m ++] = p[i]; 62 } 63 if(n > 1) --m; 64 return m; 65 } 66 67 void solve(){ 68 n = convex_hull(); 69 if(n == 1){//当只有一个点时,绳子长度为0 70 puts("0.00"); 71 return ; 72 } 73 if(n == 2){//当只有两个点时,绳子长度为两点之间的长度 74 printf("%.2lf ", length(stack[0] - stack[1])); 75 return ; 76 } 77 double ans = 0;//绳子的累加长度 78 stack[n] = stack[0];//为了算第n点到第1点的距离 79 for(int i = 0; i < n; ++i){ 80 ans += length(stack[i] - stack[i + 1]); 81 } 82 printf("%.2lf ", ans); 83 } 84 85 int main(){ 86 while(input()){ 87 solve(); 88 } 89 return 0; 90 }