좌표평면의 점들의 좌표가 주어지고, 모든 점들을 포함하는 가장 작은 볼록 다각형인 Convex Hull을 찾는 문제이다.
Jarvis March Algorithm(=Gift Wrapping - 선물 포장 알고리즘)으로 문제를 해결한다.
Problem
One day, a lawn in the centre of campus became infested with Frosh. In an effort to beautify the campus, one of our illustrious senior classmen decided to round them up using a length of pink silk. Your job is to compute how much silk was required to complete the task. The senior classman tied the silk to a telephone post, and walked around the perimeter of the area containing the Frosh, drawing the silk taught so as to encircle all of them. He then returned to the telephone post. The senior classman used the minimum amount of silk necessary to encircle all the frosh plus one extra metre at each end to tie it. You may assume that the telephone post is at coordinates (0,0), where the first dimension is North/South and the second dimension is East/West. The coordinates of the Frosh are given in metres relative to the post. There are no more than 1000 Frosh.
Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs. The input consists of a line specifying the number of Frosh, followed by one line per Frosh with two real numbers his or her position.
Output
For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line. The output consists of a single number - the length of silk in metres, to two decimal places.
Sample Input
1
4
1.0 1.0
-1.0 1.0
-1.0 -1.0
1.0 -1.0
Sample Output
10.83
#define _CRT_SECURE_NO_WARNINGS
#define MAX 1000
#define NUMBER_OF_FILES 5
#define STACK_SIZE 100
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct Point {
int name;
float x;
float y;
float angle;
}point[100];
double t_dist;
double silk[10];
float ccw(int p1, int p2, int p3) {
return (point[p2].x - point[p1].x) * (point[p3].y - point[p1].y) - (point[p3].x - point[p1].x) * (point[p2].y - point[p1].y);
}
float ComputeAngle(int p1, int p2) {
float dx, dy;
float angle;
dx = point[p2].x - point[p1].x;
dy = point[p2].y - point[p1].y;
if ((dx >= 0) && (dy == 0))
angle = 0;
else {
angle = fabs(dy) / (fabs(dx) + fabs(dy));
if ((dx < 0) && (dy >= 0))
angle = 2 - angle;
else if ((dx <= 0) && (dy < 0))
angle = 2 + angle;
else if ((dx > 0) && (dy < 0))
angle = 4 - angle;
}
return (angle * 90);
}
void swap(struct Point* arr, int a, int b)
{
struct Point temp;
temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
double distance(float x1, float y1, float x2, float y2) {
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
void Jarvis_March(int set, int size, int min_x, int min_y) {
int result[100];
int count = 0;
float lowest = MAX;
int p = min_y;
int temp;
for (int i = 1; i <= size; i++) {
result[count] = p;
count++;
if ((p == min_x) && count > 1) {
break;
}
for (int j = 1; j <= size; j++) {
if ((ComputeAngle(p, j) < lowest) && (p != j)) {
lowest = ComputeAngle(p, j);
temp = j;
}
}
p = temp;
lowest = MAX;
}
printf("\n");
int n = 0;
while (result[n] > 0) {
n++;
}
int seg = 0;
for (int i = 0; i < n - 2; i++) {
if (ccw(result[i], result[i + 1], result[i + 2]) == 0) {
seg++;
for (int j = i; j < n - 2; j++) {
result[j + 1] = result[j + 2];
}
}
}
n = 0;
while (result[n] > 0) {
n++;
}
printf("\n");
n--;
for (int i = 0; i < n; i++) {
t_dist += distance(point[result[i]].x, point[result[i]].y, point[result[i + 1]].x, point[result[i + 1]].y);
}
if (!(point[result[0]].x == point[result[n]].x && point[result[0]].y == point[result[n]].y)) {
t_dist += distance(point[result[n]].x, point[result[n]].y, point[result[0]].x, point[result[0]].y);
}
float min = MAX;
for (int i = 0; i <= n; i++) {
if (distance(point[result[i]].x, point[result[i]].y, 0, 0) < min)
min = distance(point[result[i]].x, point[result[i]].y, 0, 0);
}
t_dist += 2 * min;
printf("total distance : %f\n", t_dist);
silk[set] = t_dist;
t_dist = 0;
set = 0;
}
int minimum_x(int size) {
int min_x = 0, x = MAX;
for (int i = 1; i <= size; i++) {
if (point[i].x < x) {
x = point[i].x;
min_x = i;
}
}
return min_x;
}
int minimum_y(int size) {
int min_y = 0, y = MAX;
for (int i = 1; i <= size; i++) {
if (point[i].y < y) {
y = point[i].y;
min_y = i;
}
}
return min_y;
}
int File_input(int i) {
char Input[5][15] = {
"Input_1.txt", "Input_2.txt", "Input_3.txt", "Input_4.txt", "Input_5.txt"
};
printf("\n\n\n");
FILE* input;
input = fopen(Input[i], "r");
int set = 0, points = 0, min_y = MAX, min_x = MAX;
double d = 0, y = MAX, min_d = MAX;
if (input != NULL) {
int a = fscanf(input, "%d", &set);
for (int n = 0; n < set; n++) {
a = fscanf(input, "%d", &points);
for (int i = 1; i <= points; i++) {
point[i].name = i;
a = fscanf(input, "%f %f", &point[i].x, &point[i].y);
}
min_y = minimum_y(points);
min_x = minimum_x(points);
Jarvis_March(n, points, min_x, min_y);
}
}
else {
printf("Error.");
exit(1);
}
fclose(input);
return set;
}
void File_output(int i) {
char Output[5][15] = {
"Output_1.txt", "Output_2.txt", "Output_3.txt", "Output_4.txt", "Output_5.txt"
};
FILE* output;
output = fopen(Output[i], "w");
if (output != NULL) {
for (int i = 0; i < 10; i++) {
if (silk[i] > 0) {
fprintf(output, "%.2f\n\n", silk[i]);
}
}
for (int i = 0; i < 10; i++)
silk[i] = 0;
}
else {
printf("Error.");
exit(1);
}
fclose(output);
}
int main(void) {
int n = 0;
for (int i = 0; i < NUMBER_OF_FILES; i++) {
File_input(i);
File_output(i);
}
}
'문제' 카테고리의 다른 글
A Marketing Strategy (Closest-pair problem) (1) | 2022.12.12 |
---|---|
[UVa - 10135] Herding Frosh (0) | 2022.11.15 |
[UVa-10137] The Trip (Thanksgiving Trip) (0) | 2022.10.28 |
[백준/BOJ-9251] LCS (0) | 2022.10.24 |
[UVa-10090] Marbles (jewel box) (0) | 2022.10.10 |