Let's define the constant INF to represent infinity, and the constant MAX as the maximum number of points in the Hamiltonian path.
#define INF 1e18
#define MAX 20
Declare an array dp that will store the values dp(S, i), which are computed dynamically. The coordinates of the bottles are stored as points (x_i, y_i)~(1 \le i \le n). The robot's initial position is stored at the point (x_0, y_0).
double dp[1 << MAX][MAX + 1];
double x[MAX], y[MAX], m[MAX][MAX];
The function solve computes the value dp(S, last) — the minimum distance required to visit all points in the set S, finishing at the vertex last. The set S is encoded by an integer mask. Then:
dp(S, last) = \min_{i \in S \setminus {last}}(dp(S \setminus {last},i) + m[i][last]),
where
m[i][last] is the distance between points i and last,
S\setminus {last} = mask~\^{}~(1<< last) is the set S without the element last.
The variable res corresponds to the cell dp[mask][last], so when res is updated, the value of dp[mask][last] is automatically updated as well.
double solve(int mask, int last)
{
double &res = dp[mask][last];
if (res == INF)
{
mask ^= (1 << last);
for (int i = 1; i < n; i++)
if ((mask & (1 << i)) && (i != last))
res = min(res, solve(mask, i) + m[i][last]);
}
return res;
}
The function f returns the shortest distance from the point (x[i], y[i]) to the edge of the table.
double f(int i)
{
return min(min(x[i], y[i]), min(l - y[i], w - x[i]));
}
The function dist returns the distance between the points (x[i], y[i]) and (x[j], y[j]).
double dist(int i, int j)
{
return sqrt((x[i] - x[j])*(x[i] - x[j]) +
(y[i] - y[j])*(y[i] - y[j]));
}
The main part of the program. Read the table dimensions w and l.
Read the number of bottles n and their coordinates (x[i], y[i]).
scanf("%d", &n);
for (i = 1; i <= n; i++)
scanf("%lf %lf", &x[i], &y[i]);
The robot’s initial coordinates are stored in (x[0], y[0]).
scanf("%lf %lf", &x[0], &y[0]);
We add a zero vertex to the n bottles, corresponding to the robot's initial position. After that, n is increased by one and becomes the total number of vertices in the graph. The graph vertices are numbered 0, 1, ..., n - 1.
Let's compute all pairwise distances between the bottles. The distance between bottles i and j is defined as the minimum path the robot must travel from bottle i to bottle j, with the requirement that it must touch the edge of the table.
for (i = 1; i < n - 1; i++)
for (j = i + 1; j < n; j++)
m[i][j] = m[j][i] =
min(
min(sqrt((x[i] + x[j])*(x[i] + x[j]) + (y[i] - y[j])*(y[i] - y[j])),
sqrt((2 * w - x[i] - x[j])*(2 * w - x[i] - x[j]) +
(y[i] - y[j])*(y[i] - y[j]))),
min(sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] + y[j])*(y[i] + y[j])),
sqrt((x[i] - x[j])*(x[i] - x[j]) +
(2 * l - y[i] - y[j])*(2 * l - y[i] - y[j])))
);
Initially, the values of dp(S, i) are unknown, so we assign them positive infinity.
for (i = 0; i < 1 << n; i++)
for (j = 0; j < n; j++)
dp[i][j] = INF;
The set {0} corresponds to the mask 1. Set dp(\{0\}, 0) = 0, since the minimum path from the zero vertex to itself without visiting other vertices is zero. The variable total will store the required minimum length of the Hamiltonian path.
dp[1][0] = 0; total = INF;
for (i = 1; i < n; i++) dp[1 | (1 << i)][i] = dist(0, i);
Find the Hamiltonian path of minimum length. The value 2n - 1 corresponds to the set of all vertices \{0, 1, 2, ..., n - 1\}. Compute the minimum among all values:
dp(\{0, 1, 2, ..., n - 1\}, i) + f(i), 1 \le i < n
After obtaining the minimum length of the Hamiltonian path, we must add the distance the robot needs to travel to throw the final bottle i off the edge of the table — this distance is f(i).
for (i = 1; i < n; i++)
total = min(total, solve((1 << n) - 1, i) + f(i));
Print the required minimum path length.
printf("%.6lf\n", total);
Comments