Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
辛苦了一晚上,终于AC了。graham + RC OR jarvis + RC简单的graham(极角排序) + RC , 经典算法。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX 50000 typedef struct { double x; double y; }point; double cal_d (point a, point b); int cmp (point *a, point *b); void swap (point *s, int a, int b); int is_left (point a, point b, point c); int graham_scan (point *s, point *stack, int n); double rotating_calipers (point *value, int n); void cal_line (point *value, int index, int n, double *a, double *b, double *c); point p_set[MAX], set[MAX]; int main() { int n; int i, j; double min_y, sum; point stack[MAX]; while (scanf ("%d", &n) == 1) { min_y = 10000000; j = 0; for (i = 0; i < n; i ++) { scanf ("%lf%lf", &p_set[i].x, &p_set[i].y); if (p_set[i].y < min_y) { min_y = p_set[i].y; j = i; } else if (p_set[i].y == min_y && p_set[i].x < p_set[j].x) { j = i; } } if (j != 0) { swap (p_set, j, 0); // 极点放在第一个 } if (n > 3) { qsort (p_set + 1, n - 1, sizeof (point), cmp); // 极角排序 } j = 0; for (i = 0; i < n - 1; i ++) // 去重 { if (i == 0 || is_left (p_set[i + 1], p_set[i], p_set[0])) { set[j].x = p_set[i].x; set[j ++].y = p_set[i].y; } } set[j].x = p_set[i].x; set[j ++].y = p_set[i].y; j = graham_scan (set, stack, j); // 生成凸包stack sum = rotating_calipers (stack, j); // RC printf ("%d\n", (int)(sum * sum)); } return 0; } int is_left (point c, point b, point a) // 叉积判别方向 { point p1, p2; double v; p2.x = b.x - a.x; p2.y = b.y - a.y; p1.x = c.x - a.x; p1.y = c.y - a.y; v = p1.x * p2.y - p1.y * p2.x; if (v > 0.000000001) { return 1; } else if (v < -0.000000001) { return -1; } else { return 0; } } int graham_scan (point *s, point *stack, int n) { int i; int top = 0; stack[top].x = s[0].x; stack[top ++].y = s[0].y; stack[top].x = s[1].x; stack[top ++].y = s[1].y; stack[top].x = s[2].x; stack[top ++].y = s[2].y; if (n <= top) { return n; } for (i = 3; i < n; i ++) { while (is_left (s[i], stack[top - 1], stack[top - 2]) >= 0) { top --; } stack[top].x = s[i].x; stack[top ++].y = s[i].y; } return top; } void swap (point *s, int a, int b) { double temp; temp = s[a].x; s[a].x = s[b].x; s[b].x = temp; temp = s[a].y; s[a].y = s[b].y; s[b].y = temp; } int cmp (point *a, point *b) // 比较函数 { int v = is_left (*b, *a, p_set[0]); if (v > 0) { return 1; } else if (v == 0) { if (cal_d (*b, p_set[0]) > cal_d (*a, p_set[0])) // 将距离远的排在后面,方便处理 { return -1; } else { return 1; } } else { return -1; } } double cal_d (point a, point b) { return sqrt ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double rotating_calipers (point *value, int n) { int i, j; double d, max, temp; double a, b, c; if (n < 2) { return 0; } if (n < 3) { return cal_d (value[0], value[1]); } max = 0; for (j = 2, i = 0; i < n; i ++) { temp = 0; cal_line (value, i, n, &a, &b, &c); // 计算直线 while (1) // 求到直线具有最大距离的凸点 { d = fabs (a * value[j % n].x + b * value[j % n].y + c) / sqrt (a * a + b * b); if (temp < d) { temp = d; } else { j = j - 1; break; } j ++; } d = cal_d (value[i], value[j % n]); if (d > max) { max = d; } d = cal_d (value[(i + 1) % n], value[j % n]); if (d > max) { max = d; } } return max; } void cal_line (point *value, int index, int n, double *a, double *b, double *c) { if (value[index].x == value[(index + 1) % n].x) { *a = 1; *b = 0; *c = -value[index].x; } else if (value[index].y == value[(index + 1) % n].y) { *a = 0; *b = 1; *c = -value[index].y; } else { *a = (value[index].y - value[(index + 1) % n].y) / (value[index].x - value[(index + 1) % n].x); *b = -1; *c = value[index].y - *a * value[index].x; } } // jarvis(卷包裹法) + RC // RC , cal_line 函数同上 #include<stdio.h> #include <math.h> #include <string.h> #define MAX 10 typedef struct { double x; double y; }point; void swap (point *s, int a, int b); double cal_d (point a, point b); int direction (point c, point b, point a); int jarvis (point *tree, point *value, int n); double rotating_calipers (point *value, int n); void cal_line (point *value, int index, int n, double *a, double *b, double *c); point tree[MAX]; point value[MAX]; int main() { int n; int i, j; int mark; double max; double min_y; while (scanf ("%d", &n) == 1) { min_y = 10000000; for (i = 0; i < n; i ++) { scanf ("%lf%lf", &tree[i].x, &tree[i].y); if (tree[i].y < min_y) { min_y = tree[i].y; mark = i; } else if (tree[i].y == min_y && tree[i].x < tree[mark].x) { mark = i; } } swap (tree, 0, mark); j = jarvis (tree, value, n); max = rotating_calipers (value, j); printf ("%d\n", (int)(max * max)); } } void swap (point *s, int a, int b) { double temp; temp = s[a].x; s[a].x = s[b].x; s[b].x = temp; temp = s[a].y; s[a].y = s[b].y; s[b].y = temp; } double cal_d (point a, point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } int direction (point c, point b, point a) { double v; point p1, p2; p1.x = c.x - a.x; p1.y = c.y - a.y; p2.x = b.x - a.x; p2.y = b.y - a.y; v = p1.x * p2.y - p2.x * p1.y; if (v > 0.000000001) { return 1; } else if (v < -0.000000001) { return -1; } else { return 0; } } int jarvis (point *tree, point *value, int n) { int i, j, k; int mark, dir; int used[MAX]; memset (used, 0, sizeof (used)); k = i = 0; while (used[i] == 0) { mark = i; value[k].x = tree[i].x; value[k ++].y = tree[i].y; for (j = 0; j < n; j ++) { if (j == i) { continue; } dir = direction (tree[j], tree[mark], tree[i]); if (dir == 0) { if (cal_d (tree[j], tree[i]) > cal_d (tree[mark], tree[i])) { mark = j; } } else if (dir > 0) { mark = j; } } used[i] = 1; i = mark; } return k; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator