题目的要求是求一圈建筑物围一圈围墙且围墙离建筑物的距离最小为L,思路是对于一个建筑物的围墙周长最小应该是建筑物的所有点用一个凸包包围后的周长,再加上由于距离最小我注释说c++编译的原因是,这用c++编译器最后AC了,但是我一开始是用g++编译导致一直结果是WA ,主要本地编译器可以自动四舍五入,所以以为问题不会出在这。然后我一直在想自己哪里错了,后来一个有经验的师兄发现我的那样写法在g++可能不会自动四舍五入,换了个写法 printf("%d\n",int(len+0.5));再提交就过了,所以也是吃一堑长一智,还是自己实现四舍五入来的保险,因为不知道到底哪些编译器会帮你实现哪些又不会。大家共勉!(代码写的不好,主要是想和大家分享下这个小经验)成的圆弧将构成一个圆(多边形的外角和为360度,所以所有的围墙上的圆弧刚好是一个圆),因此再加上以L为半径的圆的周长即可。
所以主要是求凸包。用的是Graham,点的排序用极角排序实现。
以下是代码实现。错了好几次后,发现精度问题,也是参考了别人的代码实现了一个解决方法。主要被这道题一直坑的一个点是最后输出要四舍五入,我用的是
printf("%.0lf\n",len);//c++编译
我注释说c++编译的原因是,这用c++编译器最后AC了,但是我一开始是用g++编译导致一直结果是WA ,主要本地编译器可以自动四舍五入,所以以为问题不会出在这。然后我一直在想自己哪里错了,后来一个有经验的师兄发现我的那样写法在g++可能不会自动四舍五入,换了个写法 printf("%d\n",int(len+0.5));再提交就过了,所以也是吃一堑长一智,还是自己实现四舍五入来的保险,因为不知道到底哪些编译器会帮你实现哪些又不会。大家共勉!(代码写的不好,主要是想和大家分享下这个小经验)
#include <iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<stack>
#define EPS 1e-8
#define PI 3.1415926535897932384626
using namespace std;
struct node{
double x,y;
double angle;
node(double x1,double y1){x=x1,y=y1;}
};
node * nodes[1010],*convex[1010],*n0;
int n ,l=0,r;
double leftx=10010.0,lefty=10010.0;
double dist(node *n1, node* n2){
return sqrt( (n1->x - n2->x )* (n1->x - n2->x ) + (n1->y - n2->y )* (n1->y - n2->y ));
}
int sgn(double x)
{
if (fabs(x) < EPS)
return 0;
return x < 0 ? -1 : 1;
}
double direct(node* n1, node *n2,node *n3){
return (n2->x -n1->x)*(n3->y -n1->y)-(n2->y -n1->y)*(n3->x -n1->x);
}
bool cmp( node * n1, node *n2){
if(sgn(direct(n0,n1,n2))>0 || ( sgn(direct(n0,n1,n2))==0 && dist(n1,n0)<dist(n0,n2)))
return true;
else
return false;
}
/*double cross_product( node* n1, node *n2,node *n3){
double x1,y1,x2,y2;
x1=n2->x - n1->x;
y1=n2->y - n1->y;
x2= n3->x - n2->x;
y2= n3->y - n2->y;
double s=x1*y2 -y1*x2;
return s;
}*/
void Graham(){
l=0;
convex[l++] = n0;//cout<<convex[0]->x<<" "<<convex[0]->y<<endl;
for(int i=0;i<n;i++){
if(nodes[i]->x==leftx && nodes[i]->y==lefty) continue;
while(l>1&&cross_product(convex[l-2] , convex[l-1] ,nodes[i])<= 0){
l--;
}
convex[l++]=nodes[i];//cout<<nodes[i]->x<<" "<<nodes[i]->y<<endl;
}
}
double getlength(){
double len=0.0;//cout<<convex[0]->x<<" "<<convex[0]->y<<endl;
for(int i=1;i<l ;i++){//cout<<convex[i]->x<<" "<<convex[i]->y<<endl;
len+=dist(convex[i] ,convex[i-1]);
}
len+=dist(convex[l-1] ,convex[0]);
len+=2*r*PI;
return len;
}
int main()
{
scanf("%d%d",&n,&r);
for(int i=0 ;i<n ;i ++ ){
nodes[i]=new node(0,0);
scanf("%lf%lf",&nodes[i]->x,&nodes[i]->y);
if( nodes[i]->x <leftx || nodes[i]->x == leftx && lefty > nodes[i]->y){//找到左下角的点
leftx = nodes[i]->x;
lefty = nodes[i]->y;
}
}
n0=new node(leftx,lefty);
sort(nodes,nodes+n,cmp);
Graham();
double len=getlength();
// cout<<len<<endl;
printf("%.0lf\n",len);//c++编译
return 0;
}