#include <iostream>
#include <vector>
#include <array>
#include <list>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <tuple>
#include <bitset>
#include <memory>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <numeric>
#include <climits>
#include <cfloat>
#include <cassert>
#include <random>

struct Point {
	long long int x, y;
	double distance(const Point& that) const;
	bool operator==(const Point& that) const;
	bool operator!=(const Point& that) const;
};
struct Vector {
	long long int x, y;
	double norm() const;
	long long int cross(const Vector& that) const;
};
Vector operator-(const Point& to, const Point& from) {
	return Vector{ to.x - from.x, to.y - from.y };
}
void remove_convex(const std::vector<Point>& points, std::vector<int>& result, const int from, const int to, const int remove1, const int remove2 = -1) {
	result.clear();
	for (auto i = from; i != to; i = (i + 1) % points.size()) if (points[i] != points[remove1] && (remove2 == -1 || points[i] != points[remove2])) {
		while (result.size() >= 2) {
			if ((points[result[result.size() - 2]] - points[result[result.size() - 1]]).cross(points[i] - points[result[result.size() - 1]]) < 0) {
				result.pop_back();
			}
			else {
				break;
			}
		}
		if (result.empty() || points[result.back()] != points[i]) result.push_back(i);
	}
	while (result.size() >= 2 && (points[result[result.size() - 2]] - points[result[result.size() - 1]]).cross(points[to] - points[result[result.size() - 1]]) < 0) {
		result.pop_back();
	}
	if (result.empty() || points[result.back()] != points[to]) result.push_back(to);
}
void map(std::vector<Point>& map, const std::vector<int>& index, const std::vector<Point>& points) {
	map.clear();
	for (const auto i : index) map.push_back(points[i]);
}
int main() {
	int n; std::cin >> n;
	std::vector<Point> points(n); for (auto& p : points) std::cin >> p.x >> p.y;
	std::sort(points.begin(), points.end(), [](const Point& a, const Point& b) {return a.x == b.x ? a.y < b.y : a.x < b.x; });
	for (int i = points.size() - 2; i > 0; --i) points.push_back(points[i]);
	std::vector<int> convex;
	for (auto i = 0; i < points.size(); ++i) {
		while (convex.size() >= 2) {
			if ((points[convex[convex.size() - 2]] - points[convex[convex.size() - 1]]).cross(points[i] - points[convex[convex.size() - 1]]) < 0) {
				convex.pop_back();
			}
			else {
				break;
			}
		}
		convex.push_back(i);
	}
	while ((points[convex[convex.size() - 2]] - points[convex[convex.size() - 1]]).cross(points[0] - points[convex[convex.size() - 1]]) < 0) {
		convex.pop_back();
	}
	std::vector<int> index, second;
	std::vector<Point> index_map, second_map;
	std::vector<double> reduce_single(convex.size(), 0);
	double max_reduce_double = 0, max_except_zero = 0;
	for (auto i = 0; i < convex.size(); ++i) {
		auto prev = convex[(convex.size() + i - 1) % convex.size()];
		auto current = convex[i];
		auto next = convex[(i + 1) % convex.size()];
		reduce_single[i] = points[prev].distance(points[current]) + points[current].distance(points[next]);
		remove_convex(points, index, prev, next, current);
		for (auto j = 1; j < index.size(); ++j) {
			reduce_single[i] -= points[index[j]].distance(points[index[j - 1]]);
		}
		map(index_map, index, points);
		index.push_back(convex[(i + 2) % convex.size()]);
		for (auto j = 1; j + 1 < index.size(); ++j) {
			remove_convex(points, second, index[j - 1], index[j + 1], current, index[j]);
			double reduce = points[index[j - 1]].distance(points[index[j]]) + points[index[j]].distance(points[index[j + 1]]);
			for (auto k = 1; k < second.size(); ++k) {
				reduce -= points[second[k]].distance(points[second[k - 1]]);
			}
			map(second_map, second, points);
			max_reduce_double = std::max(max_reduce_double, reduce + reduce_single[i]);
		}
	}
	for (auto i = 3; i + 1 < convex.size(); ++i) {
		max_except_zero = std::max(max_except_zero, reduce_single[i - 2]);
		max_reduce_double = std::max({ max_except_zero + reduce_single[i], max_reduce_double, reduce_single[0] + reduce_single[i] });
	}
	max_reduce_double = std::max(max_reduce_double, reduce_single.back() + max_except_zero);
	std::cout << std::setprecision(15) << std::fixed << max_reduce_double << '\n';
}

double Point::distance(const Point& that) const
{
	return (*this - that).norm();
}

bool Point::operator==(const Point& that) const
{
	return x == that.x && y == that.y;
}

bool Point::operator!=(const Point& that) const
{
	return !(*this == that);
}

double Vector::norm() const
{
	return std::sqrt(x * x + y * y);
}

long long int Vector::cross(const Vector& that) const
{
	return x * that.y - y * that.x;
}



Measured memory_bytes: 6112