您的位置:首页 > 产品设计 > UI/UE

2013 多校第七场 hdu 4667 Building Fence(计算几何、凸包)

2013-08-13 19:19 405 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4667

题目大意:给你n个圆,m个三角形,两两不重叠,问你把他们全都围起来的最短的篱笆的长度。

思路:我的做法是暴力,三角形不用处理,因为就三个点,圆的话,直接枚举角度,把它拆成点,然后上凸包,飘时限和精度。。。

经过不懈的努力之后,终于用G++ 900ms+ 飘过了,补充一句,C++TLE。。 = =

比赛的时候剩下一个半小时搞这道,因为搞计算几何的队友不在,木有搞过计算几何,也木有模板,明确暴力的思路后,就去网上乱找模板,结果找 cuo 了,最后还是没A。。 T^T

暴力代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const double PI = acos(-1.0);

const int MAXN = 11111111 ;

struct Point {
double x, y;
Point(){}
Point(double a,double b): x(a),y(b) {}
Point operator - (const Point& t) const {
Point tmp;
tmp.x = x - t.x;
tmp.y = y - t.y;
return tmp;
}
Point operator + (const Point& t) const {
Point tmp;
tmp.x = x + t.x;
tmp.y = y + t.y;
return tmp;
}
bool operator == (const Point& t) const {
return fabs(x-t.x) < eps && fabs(y-t.y) < eps;
}
}GP,point[MAXN];
struct Cir {
Point ct;
double r;
};

inline double Cross(Point a, Point b, Point c) {					// 叉积
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
inline double PPdis(Point a, Point b) {								// 点点距离
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double PLdis(Point p,Point l1,Point l2){						// 点线距离
return fabs(Cross(p,l1,l2))/PPdis(l1,l2);
}
inline bool same_dir(Point a, Point b) {							// 向量是否同向
return fabs(a.x*b.y-b.x*a.y) < eps && a.x*b.x > -eps && a.y*b.y > -eps;
}
bool dotOnSeg(Point p, Point s, Point e) {							// 点是否在线段上
if ( p == s || p == e )		// 看具体情况端点是否合法
return true;
return fabs((p-s).x*(p-e).y - (p-e).y*(p-s).x) < eps &&
(p.x-s.x)*(p.x-e.x)<eps && (p.y-s.y)*(p.y-e.y)<eps;
}
bool Intersect(Point p1, Point p2, Point p3, Point p4, Point& p) {	// 直线相交
double a1, b1, c1, a2, b2, c2, d;
a1 = p1.y - p2.y; b1 = p2.x - p1.x; c1 = p1.x*p2.y - p2.x*p1.y;
a2 = p3.y - p4.y; b2 = p4.x - p3.x; c2 = p3.x*p4.y - p4.x*p3.y;
d = a1*b2 - a2*b1;
if ( fabs(d) < eps )	return false;
p.x = (-c1*b2 + c2*b1) / d;
p.y = (-a1*c2 + a2*c1) / d;
return true;
}
bool cmpyx(Point a, Point b) {
if ( a.y != b.y )
return a.y < b.y;
return a.x < b.x;
}
void Grahamxy(Point *p, int &n) {									// 水平序(住:两倍空间)
if ( n < 3 )
return;
int i, m=0, top=1;
sort(p, p+n, cmpyx);
for (i=n; i < 2*n-1; i++)
p[i] = p[2*n-2-i];
for (i=2; i < 2*n-1; i++) {
while ( top > m && Cross(p[top], p[i], p[top-1]) < eps )
top--;
p[++top] = p[i];
if ( i == n-1 )	m = top;
}
n = top;
}

bool cmpag(Point a, Point b) {
double t = (a-GP).x*(b-GP).y - (b-GP).x*(a-GP).y;
return fabs(t) > eps ? t > 0 : PPdis(a, GP) < PPdis(b, GP);
}
void Grahamag(Point *p, int &n) {								// 极角序
int i, top = 1;
GP = p[0];
for (i=1; i < n; i++) if(p[i].y<GP.y-eps || (fabs(p[i].y-GP.y)<eps && p[i].x<GP.x)) {
GP = p[i];
}
sort(p, p+n, cmpag);
for ( i=2; i < n; i++ ) {
while ( top > 0 &&  Cross(p[top], p[i], p[top-1]) < eps )
top--;
p[++top] = p[i];
}
p[++top] = p[0];
n = top;
}

int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int tot = 0;
double x,y,r;
for(int i = 0;i<n;i++)
{
scanf("%lf%lf%lf",&x,&y,&r);
for(double j = 0;j<2*PI;j += 0.0032)
{
point[tot++] = Point(x+r*cos(j),y+r*sin(j));
}
}
for(int i = 0;i<m;i++)
for(int j = 0;j<3;j++)
{
scanf("%lf%lf",&x,&y);
point[tot++] = Point(x,y);
}
Grahamxy(point,tot);
/*
printf("tot = %d\n",tot);
for(int i = 0;i<tot;i++)
printf("i = %d,x = %lf,y = %lf\n",i,point[i].x,point[i].y);
*/
double ans = 0;
Point pre = point[0];
for(int i = 1;i<tot;i++)
{
ans += PPdis(point[i],pre);
pre = point[i];
}
ans += PPdis(point[0],pre);
printf("%.5f\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: