The area of a triangle with sides and is computed in the function area using Heron's formula:
Let be some subset of the available fence pieces. The function FindSol() finds the maximum area that can be enclosed using triangles formed from the pieces in this subset.
The variable represents a subset mask: it is a -bit number whose -th bit is equal to if the subset contains the piece fences[i], and otherwise.
The answer to the problem is the value FindSol(2^n - 1), where is the number of elements in the array .
The values of all possible masks lie in the range from to 2^{16} - 1 (since, according to the constraints, there are no more than fence pieces). The array entry best[mask] stores the maximum area that can be enclosed by the subset of fence pieces corresponding to the mask .
To compute FindSol() all possible triples of fence pieces i, j, k that are present in should be enumerated. For each triple, the triangle inequality is checked to ensure that a triangle can be formed from these pieces. If a triangle is possible, the following sum is computed:
Next, all such triples (i, j, k) are considered, and the one for which this sum is maximal is selected. This maximum value is assigned to best[mask]:
If the lengths of the fence pieces are initially sorted, then when checking the triangle inequality (for a triangle with sides fences[i], fences[j], fences[k]), it is sufficient to check only one condition:
Since after sorting we have
it always follows that
Example
In the first test, the optimal triangles to construct have sides (4, 5, 6) and (7, 8, 9). The total enclosed area in this case is .
In the second test, the answer is , since no triangle can be formed from the available fences.
In the third test, a triangle with sides (4, 4, 4) should be constructed. Note that fence lengths can be repeated.
Algorithm implementation
Declare the global variables.
#define MAX 16
double best[1<<MAX];
int f[MAX+1];The function area computes the area of a triangle using Heron's formula.
double area(int a, int b, int c)
{
double p = (a + b + c) / 2.0;
return sqrt(p * (p - a) * (p - b) * (p - c));
}The function FindSol returns the maximum area that can be enclosed using triangles formed from the fences included in the mask .
double FindSol(int mask)
{If the value in the array best[mask] is greater than or equal to zero, it has already been computed, and the function returns this value. This avoids redundant computations and speeds up the algorithm.
if (best[mask] >= 0.0) return best[mask];Initialize best[mask] = 0.
best[mask] = 0;Iterate over all possible triples of indices (i, j, k) such that the corresponding fences are included in .
for (int i = 0; i < n - 2; i++) if (mask & (1 << i))
for (int j = i + 1; j < n - 1; j++) if (mask & (1 << j))
for (int k = j + 1; k < n; k++) if (mask & (1 << k))Check the triangle existence condition. Since the fences are initially sorted, this condition is sufficient to ensure that a triangle can be formed.
if (f[i] + f[j] > f[k]) If the triangle exists, compute the sum:
the area of the current triangle area(f[i], f[j], f[k]);
plus the maximum area that can be enclosed with the remaining fences, excluding those used in this triple:
best[mask] = max(best[mask], area(f[i],f[j],f[k]) +
FindSol(mask ^ (1 << i) ^ (1 << j) ^ (1 << k)));
return best[mask];
}The main part of the program. Read the number of fences .
while (scanf("%d",&n) == 1)
{
memset(f,0,sizeof(f));Read the lengths of the fences and sort them in non-decreasing order.
for (i = 0; i < n; i++) scanf("%d",&f[i]);
sort(f,f + n); Initialize the array .
for (i = 0; i < (1 << MAX); i++) best[i] = -1.0;Compute and print the answer.
printf("%.4lf\n",FindSol((1 << n) - 1));
}