| ||||||||||
| 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