Wall题意 已知一个多边形的城堡,现在用用最少的石头建造环绕城堡的城墙,但是城墙不能离城堡超过一定的距离L。问这个城墙最小的长度。思路 首先知道,对于一条边,我们只需将它往外平移L个长度即可,至于顶点肯定做一个半径为L的圆(一部分)将两边连接起来,如果该顶点是一个凹点,那肯定没有将两边的点直接相连短,所以需要先构造凸包(如果不知道为什么要构造凸包,可以画一下,很好看出来)。至于圆弧的那部分,需要计算角度,容易知道图中角度1和角度2互补,先将角度2利用点乘公式(不能用叉乘,因为用asin函数一个值对应两个角度)计算出来,就知道角度1了。构造凸包的算法以及模板代码中参考《挑战程序与设计竞赛》 代码
#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std
;
typedef long long ll
;
typedef unsigned long ul
;
typedef unsigned long long ull
;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair
<ll
,ll
> pa
;
const int dir_4
[4][2]={-1,0,0,1,1,0,0,-1};
const int dir_8
[8][2]={-1,-1,-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1};
const ll INF
=0x3f3f3f3f3f3f3f3f;
const double eps
=1e-8;
const int MAX_N
=1e3+7;
double add(double a
,double b
){
if(fabs(a
+b
)<eps
)
return 0;
return a
+b
;
}
struct P
{
double x
,y
;
P(){}
P(double x
,double y
):x(x
),y(y
){}
P operator
+(P p
){
return P(add(x
,p
.x
),add(y
,p
.y
));
}
P operator
-(P p
){
return P(add(x
,-p
.x
),add(y
,-p
.y
));
}
P operator
*(double d
){
return P(x
*d
,y
*d
);
}
double dot(P p
){
return add(x
*p
.x
,y
*p
.y
);
}
double det(P p
){
return add(x
*p
.y
,-y
*p
.x
);
}
bool operator
<(const P
&p
)const{
if(x
!=p
.x
)
return x
<p
.x
;
return y
<p
.y
;
}
double dis(P p
){
return sqrt((x
-p
.x
)*(x
-p
.x
)+(y
-p
.y
)*(y
-p
.y
));
}
}pos
[MAX_N
],pos_hull
[MAX_N
];
double L
;
int N
,cnt
;
int main()
{
int i
,j
,k
;
scf("%d %lf",&N
,&L
);
for(i
=0;i
<N
;i
++){
scf("%lf %lf",&pos
[i
].x
,&pos
[i
].y
);
}
sort(pos
,pos
+N
);
cnt
=0;
for(i
=0;i
<N
;i
++){
while(cnt
>1&&(pos_hull
[cnt
-1]-pos_hull
[cnt
-2]).det(pos
[i
]-pos_hull
[cnt
-1])<=0)
cnt
--;
pos_hull
[cnt
++]=pos
[i
];
}
k
=cnt
;
for(i
=N
-2;i
>=0;i
--){
while(cnt
>k
&&(pos_hull
[cnt
-1]-pos_hull
[cnt
-2]).det(pos
[i
]-pos_hull
[cnt
-1])<=0)
cnt
--;
pos_hull
[cnt
++]=pos
[i
];
}
cnt
--;
double res
=0;
for(i
=0;i
<cnt
;i
++){
double dis1
=pos_hull
[i
].dis(pos_hull
[(i
-1+cnt
)%cnt
]);
double dis2
=pos_hull
[i
].dis(pos_hull
[(i
+1)%cnt
]);
res
+=dis2
;
res
+=(pi
-acos((pos_hull
[(i
+1)%cnt
]-pos_hull
[i
]).dot(pos_hull
[(i
-1+cnt
)%cnt
]-pos_hull
[i
])/dis1
/dis2
))*L
;
}
prf("%.0f\n",res
);
return 0;
}