Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

辛苦了一晚上,终于AC了。graham + RC OR jarvis + RC

Posted by ProgrammingEveryday at 2012-08-21 05:36:27 on Problem 2187
简单的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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator