9 12 7 24 9 30 5 41 9 80 7 50 87 22 9 45 1 50 7 0
243.06
水平序 Graham 扫描算法
这题要注意n = 1,2的时候需要特判,1的时候好理解,至于2的时候需要对答案除以二,也就是只保留一个凸壳,不明白为什么??或许是用例有错?? 我是看了DISCUSS才发现的。。。感谢大神铺路【哭
下面是我又丑又长的代码。。。。
#include <iostream> #include <cstdio> #include <algorithm> #include <stack> #include <cmath> #define eps 1e-8 using namespace std; struct point { int x, y; }; bool cmp(point a, point b) { if(a.x != b.x) return a.x < b.x; else return a.y < b.y; } double getlen(point* trees,int n) { stack<point> S; while(!S.empty()) { S.pop(); } S.push(trees[0]); S.push(trees[1]); int i; point t1, t2; int flag = 0; for(i = 2; i < n; i++) { t1 = S.top(); S.pop(); t2 = S.top(); S.push(t1); if((t1.x - t2.x) * (trees[i].y - t1.y) - (trees[i].x - t1.x) * (t1.y - t2.y) <= 0) { S.pop(); flag = 1; } if(S.size() < 2 || flag == 0) { S.push(trees[i]); } else { i--; } flag = 0; } double len = 0; t1 = S.top(); S.pop(); while(!S.empty()) { t2 = S.top(); S.pop(); len += sqrt((t1.x - t2.x) * (t1.x - t2.x) * 1.0 + (t1.y - t2.y) * (t1.y - t2.y) * 1.0); t1 = t2; } return len; } int main() { int n; point trees[110]; point ttrees[110]; while(~scanf("%d", &n) && n) { int i; for(i = 0; i < n; i++) { scanf("%d %d", &trees[i].x, &trees[i].y); } if(n == 1) { printf("0.00\n"); continue; } sort(trees, trees + n, cmp); double len1 = getlen(trees, n); int j = n - 1; for(i = 0; i < n; i++, j--) { ttrees[j] = trees[i]; } double len2 = getlen(ttrees, n); if(n != 2) printf("%.2lf\n", len1 + len2); else printf("%.2lf\n", len1); } return 0; }