要求包围所有n个点并且距所有点距离大于L的多边形周长
这个多边形的周长可以通过凸包上的边做平移加上一个半径L的圆辅助转向得到
所以就是求凸包周长加上圆周长
主要是为了试试凸包的接口,实现用的是Graham,应该是单调栈吧?
//#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
const double pi=acos(-1.0);
#define ll long long
#define pb push_back
const int maxn=1e3+56;
const double eps=1e-6;
int sgn(double x){
if(fabs(x)<eps)return 0;
if(x<0)return -1;
else return 1;
}
struct Point{
double x,y;
void input(){
scanf("%lf%lf",&x,&y);
}
Point(){}
Point(double _x,double _y){x=_x;y=_y;}
double distance(Point p){
return hypot(x-p.x,y-p.y);
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator -(const Point &b)const{
return Point(x-b.x,y-b.y);
}
double operator *(const Point &b)const{
return x*b.x+y*b.y;
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
double operator^(const Point &b)const{
return x*b.y-y*b.x;
}
bool operator ==(Point b)const{
return sgn(x-b.x)==0 && sgn(y-b.y)==0;
}
bool operator < (Point b)const{
return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
}
double len(){return hypot(x,y);}
double len2(){
return x*x+y*y;
}
Point trunc(double r){
double l=len();
if(!sgn(l))return *this;
r/=l;
return Point(x*r,y*r);
}
};
struct Line{
Point s,e;
Line(){}
Line (Point _s,Point _e){
s=_s;e=_e;
}
Line(Point p,double angle){//与x轴夹角
s=p;
if(sgn(angle-pi/2)==0)e=(s+Point(0,1));
else e=(s+Point(1,tan(angle)));
}
double length(){return s.distance(e);}
double dispointtoline(Point p){
return fabs((p-s)^(e-s))/length();
}
double dispointtoseg(Point p){
if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
return min(p.distance(s),p.distance(e));
return dispointtoline(p);
}
Point lineprog(Point p){
return s+( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
}
};
struct polygon{
int n;
Point p[maxn];
Line l[maxn];
void input(int _n){
n=_n;for(int i=0;i<n;i++)p[i].input();
}
void add(Point q){p[n++]=q;};
void getline(){
for(int i=0;i<n;i++){
l[i]=Line(p[i],p[(i+1)%n]);
}
}
struct cmp{
Point p;
cmp(const Point &p0){p=p0;}
bool operator()(const Point&aa,const Point&bb){
Point a=aa,b=bb;
int d=sgn( (a-p)^(b-p) );
if(d==0)return sgn(a.distance(p)-b.distance(p))<0;
return d>0;
}
};
void norm(){
Point mi=p[0];
for(int i=1;i<n;i++)mi=min(mi,p[i]);
sort(p,p+n,cmp(mi));
}
void Graham(polygon &convex){
norm();
int &top=convex.n;
top=0;
if(n==1){
top=1;convex.p[0]=p[0];
return;
}
if(n==2){
top=2;convex.p[0]=p[0];convex.p[1]=p[1];
if(convex.p[0]==convex.p[1])top--;return;
}
convex.p[0]=p[0];
convex.p[1]=p[1];
top=2;
for(int i=2;i<n;i++){
while(top>1 && sgn((convex.p[top-1]-convex.p[top-2])^
(p[i]-convex.p[top-2]))<=0)top--;
convex.p[top++]=p[i];
}
if(convex.n==2 && (convex.p[0]==convex.p[1]))convex.n--;
}
double getcircumference(){
double sum=0;
for(int i=0;i<n;i++)sum+=p[i].distance(p[(i+1)%n]);
return sum;
}
};
int main(){
int n,r;
while(~scanf("%d%d",&n,&r)){
polygon now;
now.input(n);
polygon convex;
now.Graham(convex);
printf("%d\n",(int)round(convex.getcircumference()+pi*2*r));
}
}
贴一个不用kb模板的轻量化板子:
//#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
const double pi=acos(-1.0);
#define ll long long
#define pb push_back
#define sqr(a) ((a)*(a))
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
const int maxn=1e3+56;
const int inf=0x3f3f3f3f;
struct Point{
double x,y;
int v,l;
Point(double a=0,double b=0){x=a;y=b;}
bool operator<(Point b)const{
return y<b.y||(y==b.y && x<b.x);
}
}p[maxn],ch[maxn<<1],tmp[maxn];
double mult(Point a,Point b,Point o){
return(a.x-o.x)*(b.y-o.y)>=(b.x-o.x)*(a.y-o.y);
}
double Graham(Point p[],int n,Point res[]){ //返回凸包周长
int top=1;
sort(p,p+n);
if(n==0)return 0;res[0]=p[0];
if(n==1)return 0;res[1]=p[1];
if(n==2)return dis(p[0],p[1])*2;
res[2]=p[2];
for(int i=2;i<n;i++){
while(top && (mult(p[i],res[top],res[top-1])))
top--;
res[++top]=p[i];
}
int len=top;
res[++top]=p[n-2];
for(int i=n-3;i>=0;i--){
while(top!=len && (mult(p[i],res[top],res[top-1])))
top--;
res[++top]=p[i];
}
double c=dis(res[0],res[top-1]);
for(int i=0;i<top-1;i++){
c+=dis(res[i],res[i+1]);
}
return c;
}
int n,kase;
int main(){
while(scanf("%d",&n)&&n){
for(int i=0;i<n;i++){
scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].v,&p[i].l);
}
int min_cut=inf,min_val=inf,ans=0;
double res_len=0;
for(int bit=0;bit<(1<<n);bit++){
int res=0,cut_val=0;
double cut_len=0;
for(int i=0;i<n;i++){
if(bit & (1<<i)){
cut_len+=p[i].l;
cut_val+=p[i].v;
}else{
tmp[res].x=p[i].x;
tmp[res++].y=p[i].y;
}
}
if(cut_val>min_val)continue;
double c=Graham(tmp,res,ch);
if(cut_len>=c){
if(cut_val<min_val || (cut_val==min_val && n-res<min_cut)){
ans=bit;
min_val=cut_val;
min_cut=n-res;
res_len=cut_len-c;
}
}
}
if(kase)puts("");
printf("Forest %d\n",++kase);
printf("Cut these trees:");
for(int i=0;i<n;i++)
if(ans&(1<<i))
printf(" %d",i+1);
printf("\nExtra wood: %.2f\n",res_len);
}
}