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 (xi,yi) (1≤i≤n). The robot's initial position is stored at the point (x0,y0).
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)=i∈S∖lastmin(dp(S∖last,i)+m[i][last]),
where
m[i][last] is the distance between points i and last,
S∖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≤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);