Andrew板子(二维凸包)
题意:
告诉你n个点,求这些点的凸包边长,或者在凸包边上点的数量。
#include <bits/stdc++.h> using namespace std; #define ll long long //#define int ll const int maxn = 1e5 + 10; const int N = 4e6 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-7; inline int rd(){ int res = 0;char ch = getchar(); while(!isdigit(ch)){if(ch == '-') ch = getchar();} while(isdigit(ch)){res = res * 10 + (ch - '0'); ch = getchar();} return res; } inline int sgn(double x){ if(fabs(x) <= eps)return 0; return x < 0 ? -1 : 1; } struct Node{ double x, y; Node(){} Node(double x, double y):x(x), y(y){} Node operator - (Node tmp){return Node(x - tmp.x, y - tmp.y);} Node operator + (Node tmp){return Node(x + tmp.x, y + tmp.y);} bool operator == (Node tmp) {return !sgn(x - tmp.x) && !sgn(y - tmp.y);} bool operator < (Node tmp){ if(sgn(x - tmp.x) != 0){ return x < tmp.x; }else{ return y < tmp.y; } } }; int n, save; // 计算叉积,小于0表示b向量在a向量的右方 double cross(Node a, Node b){ return a.x * b.y - a.y * b.x; } double getDis(Node a, Node b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } /** * @param node 点集 * @param n 点集数量 * @param res 在凸包上的点集 * @return 返回凸包上点的数量 */ int Andrew(Node *node, int n, Node *res){ sort(node, node + n); n = unique(node, node + n) - node;// 去重 int cnt = 0; for(int i = 0; i < n; i++){ while(cnt > 1 && sgn(cross(res[cnt - 1] - res[cnt - 2], node[i] - res[cnt - 2])) <= 0) cnt--; res[cnt++] = node[i]; } int j = cnt; for(int i = n - 2; i >= 0; i--){ while(cnt > j && sgn(cross(res[cnt - 1] - res[cnt - 2], node[i] - res[cnt - 2])) <= 0) cnt--; res[cnt++] = node[i]; } if(n > 1)cnt--; return cnt; } Node node[maxn], res[maxn]; int main(){ scanf("%d", &n); for(int i = 0; i < n; i++){ scanf("%lf %lf", &node[i].x, &node[i].y); } int nodes = Andrew(node, n, res); double ans = 0; if(nodes == 1)printf("0\n"); else if(nodes == 2)printf("%.2f\n", getDis(res[0], res[1])); else{ for(int i = 0; i < nodes; i++){ ans += getDis(res[i], res[(i + 1) % nodes]); } printf("%.2f\n", ans); } return 0; }

浙公网安备 33010602011771号