(Por lo que veo, el concurso en línea ya ha terminado, así que volveré a publicar mi respuesta como había prometido).
Según lo comentado por hardmath, y acordado por el OP, la solución es un polígono cíclico cuyos vértices se encuentran en un círculo común.
Obsérvese que si uno de los segmentos de la línea fuera más largo que la suma de la longitud del resto de los segmentos de la línea, no pueden formar un polígono. Por ello, sabemos que $$L_i \le \sum_{k \ne i}^{n} L_k$$ para todos $i = 1 \ldots n$ . (Esto también significa que $0 \le \theta_i \lt \pi$ .)
Cada uno de los $n$ segmentos de línea forma esencialmente un triángulo isósceles con el centro del círculo común. Dos de los lados son de longitud $r$ el radio del círculo común, y el tercero es el propio segmento de línea, de longitud $L_i$ . (Esencialmente, podemos descomponer el polígono en cuñas triangulares, siendo cada una de ellas un triángulo isósceles. Esto también significa que el orden de los segmentos de línea no afecta al área, ya que reordenar las partes triangulares no cambia sus áreas).
La longitud de un cuerda circular cumple con $$L_i = 2 r \sin\left(\frac{\theta_i}{2}\right)$$ Aquí, $\theta_i$ es el ángulo entre el $r$ -cantos de longitud en los triángulos isósceles. Resolviendo para $\theta_i$ vemos que $$\theta_i = 2 \arcsin \left( \frac{L_i}{2 r} \right) = \arccos \left( 1 - \frac{ L_i^2 }{2 r^2} \right)$$ porque $2 \arcsin(x) = \arccos(1 - 2 x^2)$ cuando $0 \le x \le 1$ .
Tenga en cuenta que esto también significa que $$\frac{d \, \theta_i}{d \, r} = - \frac{2 L}{\sqrt{4 r^4 - L^2 r^2}}$$
Para que la figura sea un polígono, la suma de los ángulos $\theta_i$ debe ser igual a $180°$ : $$\sum_{i=1}^{n} \theta_i = 2 \pi$$
Combinando las dos anteriores, y dividiendo por dos, obtenemos $$\sum_{i=1}^{n} \arcsin \left( \frac{L_i}{2 r} \right) = \pi$$ que podemos utilizar para numéricamente resolver para $r$ .
Para que cada $\theta_i$ de existir, $\max(L)/(2r) \le 1$ . Esto significa que $r \ge \max(L)/2$ y que $r_{min} = \max(L)/2$ es el radio mínimo permitido en los métodos numéricos.
También sabemos que el radio debe ser menor que la mitad del perímetro, por lo que $r_{max} = (\sum_i L_i) / 2$ .
Cuando hayamos encontrado el $r$ para lo cual $\sum_i \theta_i = 2 \pi$ podemos calcular las coordenadas de los vértices. Como los puntos deben estar en el orden de las agujas del reloj, podemos utilizar $$\begin{cases} x_i' = x_0 - r \cos \varphi_i \\ y_i' = y_0 + r \sin \varphi_i \\ \end{cases}$$ donde $$\begin{cases} x_0 = r \cos \varphi_1 \\ y_0 = -r \sin \varphi_1 \end{cases}$$ y $$\varphi_i = \begin{cases} -\frac{\theta_i}{2}, & i = 1 \\ -\frac{\theta_i}{2} + \sum_{k=1}^{i-1} \theta_i, & 2 \le i \le n \end{cases}$$ Lo anterior nos da $\varphi_1 = -\theta_1/2$ y $\varphi_2 = -\varphi_1 = \theta_1/2$ , por lo que el primer segmento de línea será vertical; $x_1 = x_2 = y_1 = 0$ , $y_2 \gt 0$ (de hecho $y_2 = L_1$ ).
Por lo tanto, lo anterior da como resultado $x_1 = 0$ , $y_1 = 0$ , $x_2 = 0$ , $y_2 = L_1$ con el resto de los vértices $(x_i, y_i)$ en el sentido de las agujas del reloj alrededor del centro en $(x_0, y_0)$ .
Este es un programa de ejemplo que lee las longitudes de las líneas desde la entrada estándar, y utiliza una búsqueda binaria para encontrar el radio con al menos seis dígitos de precisión, dando salida a las coordenadas de los vértices en la salida estándar. ejemplo.c :
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define PI 3.141592653589793238462643383279502884197
#define TWO_PI 6.283185307179586476925286766559005768394
double theta(const double L, const double r)
{
return 2.0 * asin(0.5 * L / r);
}
double d_theta(const double L, const double r)
{
const double r2 = r * r;
return -2.0 * L / (r2 * sqrt(4.0 - L * L / r2));
}
double find_radius(const double length[], const size_t count, const double epsilon, size_t *iteration_count)
{
const double min_theta = 1.0 - epsilon;
const double max_theta = 1.0 + epsilon;
double sum_length = length[0];
double max_length = length[0];
double min_radius, radius, max_radius;
size_t iterations = 0;
size_t i;
for (i = 1; i < count; i++) {
sum_length += length[i];
if (max_length < length[i])
max_length = length[i];
}
min_radius = 0.5 * max_length;
max_radius = 0.5 * sum_length;
while (1) {
double sum_theta = 0.0;
iterations++;
radius = (0.5 * min_radius) + (0.5 * max_radius);
for (i = 0; i < count; i++)
sum_theta += theta(length[i], radius);
sum_theta /= TWO_PI;
if (sum_theta >= min_theta && sum_theta <= max_theta)
break;
else
if (sum_theta < 1.0)
max_radius = radius;
else
min_radius = radius;
}
if (iteration_count)
*iteration_count = iterations;
return radius;
}
int main(void)
{
double *line_length = NULL;
size_t line_count = 0;
size_t line_maxcount = 0;
double radius, phi, x, y, x0, y0;
size_t i;
/* Read line lengths from standard input. */
while (1) {
char buffer[1024], *line;
double length;
line = fgets(buffer, sizeof buffer, stdin);
if (!line)
break;
if (sscanf(line, " %lf", &length) < 1)
break;
if (length <= 0.0)
break;
if (line_count >= line_maxcount) {
const size_t maxcount = (line_count | 255) + 257;
double *temp;
temp = realloc(line_length, maxcount * sizeof line_length[0]);
if (!temp) {
fprintf(stderr, "Out of memory.\n");
return EXIT_FAILURE;
}
line_length = temp;
line_maxcount = maxcount;
}
line_length[line_count++] = length;
}
/* Verify sanity. */
if (line_count >= 3) {
double max_length = line_length[0];
double sum_length = line_length[0];
for (i = 1; i < line_count; i++) {
sum_length += line_length[i];
if (max_length < line_length[i])
max_length = line_length[i];
}
if (max_length > sum_length - max_length) {
fprintf(stderr, "Not a valid polygon; one of the line segments is too long.\n");
return EXIT_FAILURE;
}
} else {
fprintf(stderr, "Need at least three line lengths.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Read %zu line lengths:\n", line_count);
for (i = 0; i < line_count; i++)
fprintf(stderr, "\t%.6f\n", line_length[i]);
radius = find_radius(line_length, line_count, 0.0000002, &i);
fprintf(stderr, "radius = %.6f using %zu iterations.\n", radius, i);
phi = -0.5 * theta(line_length[0], radius);
x0 = radius * cos(phi);
y0 = -radius * sin(phi);
for (i = 0; i < line_count; i++) {
x = x0 - radius * cos(phi);
y = y0 + radius * sin(phi);
phi += theta(line_length[i], radius);
printf("%.6f %.6f\n", x, y);
}
return EXIT_SUCCESS;
}
Compilarlo utilizando, por ejemplo, en Linux
gcc -Wall -O2 example.c -lm -o example
y ejecutarlo, generando digamos 10 longitudes de línea aleatorias como entrada, utilizando
awk 'BEGIN { srand(); for (i=0; i<10; i++) printf "%.6f\n", 10.0*rand() }' | ./example
Aquí hay un ejemplo de la salida, las primeras 12 líneas al error estándar, seguidas por 10 líneas a la salida estándar:
Read 10 line lengths:
1.487793
5.241667
2.002344
4.271945
7.815320
5.452837
6.012328
7.506031
3.599992
1.636063
radius = 7.377844 using 19 iterations.
0.000000 0.000000
0.000000 1.487793
2.346549 6.174880
3.990793 7.317614
8.195604 8.071990
14.300092 3.191984
14.080471 -2.256429
9.609570 -6.276271
2.286102 -4.630880
0.344424 -1.599406
0 votos
Tu punto de partida es correcto: el área máxima se obtiene con un polígono cíclico (todos los vértices se encuentran en un círculo común). No conozco una forma de encontrar el radio del círculo, salvo formar una ecuación no lineal para resolverlo en términos de ángulos subtendidos que sumen $2\pi $ .
0 votos
Sí, encontrar el radio y el centro parece ser el verdadero problema.
3 votos
Esto es un literal copy-paste de una pregunta en un concurso online calificado que aún está en curso. ¿Por qué haces trampa?
1 votos
@plamenko: Hay una política del sitio para bloquear las preguntas del concurso bajo ciertas condiciones. Puedes señalar dónde se plantea este problema en línea, o dar más información?
0 votos
@hardmath Aquí está el enlace hackerrank.com/contests/w23/challenges/enclosure
0 votos
@MangatRaiModi: Gracias. No puedo ver el problema exacto ahí ya que hay que iniciar sesión para ver el reto de siete días (que expira en unas horas). He marcado para la atención del moderador.