解题思路:
首先明确这道题是求凸包周长加上一个圆周长,即包围凸包的一个圆角多边形。因为每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧。每个圆弧的两条半径夹角与对应的凸包的内角互补。假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°。故围墙周长为=n条平行于凸包的线段+n条圆弧的长度=凸包周长+围墙离城堡距离L为半径的圆周长。
拿小媛模板做的。
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
using namespace std;
const int MAX = 120000;
const double eps = 1e-6;
const double pi=3.141592654;
bool dy(double x,double y) { return x > y + eps;} // x > y
bool xy(double x,double y) { return x < y - eps;} // x < y
bool dyd(double x,double y) { return x > y - eps;} // x >= y
bool xyd(double x,double y) { return x < y + eps;} // x <= y
bool dd(double x,double y) { return fabs( x - y ) < eps;} // x == y
struct point{ double x,y; };
point c[MAX];
double disp2p(point a,point b)
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向
{
return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
bool cmp(point a,point b) // 排序
{
double len = crossProduct(c[0],a,b);
if( dd(len,0.0) )
return xy(disp2p(c[0],a),disp2p(c[0],b));
return xy(len,0.0);
}
int stk[MAX];
int top;
double sum = 0.0;
void Graham(int n)
{
int tmp = 0;
for(int i=1; i<n; i++)//
if( xy(c[i].x,c[tmp].x) || dd(c[i].x,c[tmp].x) && xy(c[i].y,c[tmp].y) )
tmp = i;
swap(c[0],c[tmp]);
sort(c+1,c+n,cmp);
stk[0] = 0; stk[1] = 1;
top = 1;
for(int i=2; i<n; i++)
{
while( xyd( crossProduct(c[stk[top]],c[stk[top-1]],c[i]), 0.0 ) && top >= 1 )
top--;
stk[++top] = i;
}
//cout<<"top "<<top<<endl;
}
int main()
{
int n,l;
while(cin>>n>>l && n )
{
for(int i=0;i<n;i++)
cin>>c[i].x>>c[i].y;
Graham(n);
double sum=2*pi*l;
for(int i=0; i<=top; i++)
sum += disp2p(c[stk[i]],c[stk[(i+1)%(top+1)]]);
printf("%.0lf\n",sum);
}
return 0;
}