暴力+几何
注意一个很坑的地方,直线可能会经过矩形顶点
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS (1e-6)
#define MAXP 10
int dcmp(double a, double b = 0)
{
if (fabs(a - b) <= EPS)
return 0;
return a < b ? -1 : 1;
}
int n, m, p;
struct Point
{
double x, y;
Point(double _x = 0, double _y = 0)
: x(_x), y(_y) {}
} a[MAXP], center;
typedef Point Vector;
Vector operator- (const Vector &a, const Vector &b)
{
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator+ (const Vector &a, const Vector &b)
{
return Vector(a.x + b.x, a.y + b.y);
}
bool operator== (const Point &a, const Point &b)
{
return dcmp(a.x, b.x) == 0 && dcmp(a.y, b.y) == 0;
}
bool cmp(const Point &a0, const Point &b0)
{
Point a = a0 - center, b = b0 - center;
return dcmp(atan2(a.y, a.x), atan2(b.y, b.x)) < 0;
}
double cross(const Vector &a, const Vector &b)
{
return a.x * b.y - a.y * b.x;
}
double dot(const Vector &a, const Vector &b)
{
return a.x * b.x + a.y * b.y;
}
bool parallel(const Vector &a, const Vector &b)
{
return dcmp(a.x * b.y, a.y * b.x) == 0;
}
double length(const Vector &a)
{
return sqrt(a.x * a.x + a.y * a.y);
}
struct Line
{
Point p;
Vector v;
Line() {}
Line(Point _p, Vector _v)
: p(_p), v(_v) {}
} l[MAXP];
Point intersect(const Line &a, const Line &b)
{
double y = (a.v.x * a.p.y * b.v.y - a.p.x * b.v.y * a.v.y + b.p.x * b.v.y * a.v.y - b.p.y * b.v.x * a.v.y) / (a.v.x * b.v.y - b.v.x * a.v.y);
double x;
if (dcmp(a.v.y))
x = a.v.x / a.v.y * (y - a.p.y) + a.p.x;
else
x = b.v.x / b.v.y * (y - b.p.y) + b.p.x;
return Point(x, y);
}
bool inhalf(const Point &p, const Line &l)
{
return dcmp(cross(l.v, p - l.p)) >= 0;
}
bool inrec(const Point &a)
{
return dcmp(a.x) >= 0 && dcmp(a.y) >= 0 && dcmp(a.x, n) <= 0 && dcmp(a.y, m) <= 0;
}
Line inrec(const Line &l)
{
if (dcmp(l.v.x) == 0)
return Line(Point(l.p.x, 0), Vector(0, m));
if (dcmp(l.v.y) == 0)
return Line(Point(0, l.p.y), Vector(n, 0));
Point p1, p2, p3, p4;
p1 = intersect(l, Line(Point(0, 0), Vector(n, 0)));
p2 = intersect(l, Line(Point(0, 0), Vector(0, m)));
p3 = intersect(l, Line(Point(0, m), Vector(n, 0)));
p4 = intersect(l, Line(Point(n, 0), Vector(0, m)));
bool hv = false;
Point pp;
if (inrec(p1))
{
hv = true;
pp = p1;
}
if (inrec(p2))
{
if (hv && !(pp == p2))
return Line(pp, p2 - pp);
hv = true;
pp = p2;
}
if (inrec(p3))
{
if (hv && !(pp == p3))
return Line(pp, p3 - pp);
hv = true;
pp = p3;
}
return Line(pp, p4 - pp);
}
bool v[MAXP] = {0};
double ans = 1e300;
void dfs(int num, double hv)
{
if (dcmp(hv, ans) >= 0)
return;
if (num == p)
{
ans = hv;
return;
}
for (int i = 0; i < p; ++i)
if (!v[i])
{
Line x = inrec(l[i]);
for (int j = 0; j < p; ++j)
if (v[j] && !parallel(l[j].v, x.v))
{
Point p = intersect(x, l[j]);
if (dcmp(dot(x.p - p, x.p + x.v - p)) < 0)
{
if (!inhalf(x.p, l[j]))
x = Line(p, x.p + x.v - p);
else if (!inhalf(x.p + x.v, l[j]))
x = Line(x.p, p - x.p);
}
}
v[i] = 1;
dfs(num + 1, hv + length(x.v));
v[i] = 0;
}
}
int main()
{
scanf("%d%d%d", &n, &m, &p);
for (int i = 0; i < p; ++i)
{
scanf("%lf%lf", &a[i].x, &a[i].y);
center = center + a[i];
}
center.x /= p, center.y /= p;
sort(a, a + p, cmp);
for (int i = 0; i < p - 1; ++i)
l[i] = Line(a[i], a[i + 1] - a[i]);
l[p - 1] = Line(a[p - 1], a[0] - a[p - 1]);
dfs(0, 0);
printf("%.3lf\n", ans);
return 0;
}