题目链接:POJ 1113 Wal
所求周长 = 凸包周长 + 半径为L的圆的周长。
这个我不会证明,我是画了一个圆的城堡,画了一个正方形的城堡,这两种都是满足上边的公式的,然后我认为这是两个极限,中间的都满足。或许三角形城堡才是一个极限吧。
我自己写了一个卷包裹法,然后又用了一下刘汝佳的模版,速度差了一半,算法的力量真的好强大。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const double eps = 1e-10;
const int MAX_N = 1000 + 10;
const double PI = acos(-1);
struct Point
{
int x, y;
Point(int x=0, int y=0):x(x),y(y) { }
};
typedef Point Vector;
Point p[MAX_N];
Vector operator + (const Vector& A, const Vector& B)
{
return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (const Point& A, const Point& B)
{
return Vector(A.x-B.x, A.y-B.y);
}
Vector operator * (const Vector& A, double p)
{
return Vector(A.x*p, A.y*p);
}
bool operator < (const Point& a, const Point& b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x)
{
if(fabs(x) < eps)
return 0;
else
return x < 0 ? -1 : 1;
}
bool operator == (const Point& a, const Point &b)
{
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 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;
}
double Length(const Vector& A)
{
return sqrt(Dot(A, A));
}
double dist(int a, int b)
{
double x1, x2, y1, y2, res;
x1 = p[a].x, x2 = p[b].x, y1 = p[a].y, y2 = p[b].y;
res = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
return res;
}
int path[MAX_N];
int main()
{
//freopen("in.txt", "r", stdin);
int n, l;
scanf("%d%d", &n, &l);
int _minX = 10010, _minY = 10010, _start, _beg, _end, _size = 0;
double dis = 0.0;
for(int i = 0; i < n; i++)
{
scanf("%d%d", &p[i].x, &p[i].y);
if(_minY > p[i].y || (_minY == p[i].y && _minX > p[i].x))
{
_start = i;
_minY = p[i].y;
_minX = p[i].x;
}
}
_beg = _start;
path[_size++] = _start;
while(true)
{
_end = 0;
for(int i = 0; i < n; i++)
{
if(Cross(p[i] - p[_beg], p[_end] - p[_beg]) > 0 ||
((Cross(p[i] - p[_beg], p[_end] - p[_beg]) == 0) &&
dcmp(Length(p[i] - p[_beg]) - Length(p[_end] - p[_beg])) > 0))
_end = i;
}
if(_end == _start) //卷到起点了
break;
path[_size++] = _beg = _end;
}
for(int i = 0; i < _size - 1; i++)
dis += dist(path[i], path[i + 1]);
dis += dist(path[_size - 1], path[0]);
dis += 2 * PI * l;
printf("%.0f\n", dis);
return 0;
}
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const double eps = 1e-10;
const double PI = acos(-1);
const int MAX_N = 1000 + 10;
struct Point
{
int x, y;
Point(int x=0, int y=0):x(x),y(y) { }
};
typedef Point Vector;
Point p[MAX_N];
Vector operator + (const Vector& A, const Vector& B)
{
return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (const Point& A, const Point& B)
{
return Vector(A.x-B.x, A.y-B.y);
}
Vector operator * (const Vector& A, double p)
{
return Vector(A.x*p, A.y*p);
}
bool operator < (const Point& a, const Point& b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x)
{
if(fabs(x) < eps)
return 0;
else
return x < 0 ? -1 : 1;
}
bool operator == (const Point& a, const Point &b)
{
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 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;
}
double Length(const Vector& A)
{
return sqrt(Dot(A, A));
}
// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<Point> ConvexHull(vector<Point> p)
{
// 预处理,删除重复点
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size();
int m = 0;
vector<Point> ch(n+1);
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--) {
while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
ch.resize(m);
return ch;
}
// 多边形的有向面积
double PolygonArea(vector<Point> p)
{
double area = 0;
int n = p.size();
for(int i = 1; i < n-1; i++)
area += Cross(p[i]-p[0], p[i+1]-p[0]);
return area/2;
}
int n, l;
double get_dis(vector<Point> p)
{
double dis = 0;
int n = p.size();
double x1, x2, y1, y2;
for(int i = 0; i < n - 1; i++)
{
x1 = p[i].x, x2 = p[i + 1].x, y1 = p[i].y, y2 = p[i + 1].y;
dis += sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
x1 = p[n - 1].x, x2 = p[0].x, y1 = p[n - 1].y, y2 = p[0].y;
dis += sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
dis += 2 * PI * l;
return dis;
}
double torad(double deg)
{
return deg/180 * PI;
}
Vector Rotate(const Vector& A, double rad)
{
return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}
int main()
{
scanf("%d%d", &n, &l);
vector <Point> P;
int x, y;
for(int i = 0; i < n; i++)
{
scanf("%d%d", &x, &y);
P.push_back(Point(x, y));
}
printf("%.0f\n", get_dis(ConvexHull(P)));
return 0;
}