数论六之计算几何——An Easy Problem,Ancient Berland Circus,Open-air shopping malls

An Easy Problem?!

problem

就是大讨论

#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define eps 1e-6

struct vec {
	double x, y;
	vec(){}
	vec( double X, double Y ) { x = X, y = Y; }
	vec operator + ( vec t ) { return vec( x + t.x, y + t.y ); }
	vec operator - ( vec t ) { return vec( x - t.x, y - t.y ); }
	vec operator * ( double t ) { return vec( x * t, y * t ); }
	friend double dot( vec s, vec t ) { return s.x * t.x + s.y * t.y; }
	friend double cross( vec s, vec t ) { return s.x * t.y - s.y * t.x; }
};

struct point {
	double x, y;
	point(){}
	point( double X, double Y ) { x = X, y = Y; }
	point operator + ( vec t ) { return point( x + t.x, y + t.y ); }
	vec operator - ( point t ) { return vec( x - t.x, y - t.y ); }
};

struct line {
	point p; vec v;
	line(){}
	line( point P, vec V ) { p = P, v = V; }
};

point intersect( line l, line r ) {
	return l.p + l.v * ( - ( cross( r.v, r.p - l.p ) / cross( l.v, r.v ) ) );
}

bool seg_intersect( point p1, point p2, point p3, point p4 ) {
	double d1 = cross( p3 - p1, p4 - p1 ), d2 = cross( p3 - p2, p4 - p2 );
	double d3 = cross( p1 - p3, p2 - p3 ), d4 = cross( p1 - p4, p2 - p4 );
	if( d1 * d2 > 0 || d3 * d4 > 0 ) return 0;
	else return 1;
}

int main() {
	int T; double x1, x2, y1, y2;
	scanf( "%d", &T );
	while( T -- ) {
		scanf( "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );
		point p1( x1, y1 ), p2( x2, y2 );
		scanf( "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );
		point p3( x1, y1 ), p4( x2, y2 );
		if( fabs( p2.y - p1.y ) < eps || fabs( p4.y - p3.y ) < eps ) {
			printf( "0.00\n" );
			continue;//有水平线case 
		}
		if( p1.y > p2.y ) swap( p1, p2 );
		if( p3.y > p4.y ) swap( p3, p4 );
		line l( p1, p2 - p1 ), r( p3, p4 - p3 );
		if( fabs( l.v.x * r.v.y - l.v.y * r.v.x ) < eps ) {
			printf( "0.00\n" );
			continue;//两直线平行 (x1,y1)(x2,y2)->x1y2=x2y1; 
		}
		if( ! seg_intersect( p1, p2, p3, p4 ) ) {
			printf( "0.00\n" );
			continue;//无交点 
		}
		point p = intersect( l, r );
		vec y( 0, 1 );
		if( cross( l.v, y ) * cross( r.v, y ) > 0 ) {//收集部分在竖直线一侧
			if( cross( l.v, r.v ) > 0 && p4.x - p2.x >= -eps ) {
				printf( "0.00\n" );
				continue;//收集部分l在r下面 且l被r遮挡完
			} 
			if( cross( l.v, r.v ) < 0 && p2.x - p4.x >= -eps ) {
				printf( "0.00\n" );
				continue;//收集部分l在r上面 
			}
		}
		double ans_y = min( p2.y, p4.y ); 
		//相似三角形解横坐标 
		double ans_x1 = p2.x + ( p1.x - p2.x ) * ( ans_y - p2.y ) / ( p1.y - p2.y );
		double ans_x2 = p4.x + ( p3.x - p4.x ) * ( ans_y - p4.y ) / ( p3.y - p4.y );
		double ans = ( ans_x1 - ans_x2 ) * ( ans_y - p.y ) / 2;//s=底x高/2 
		printf( "%.2f\n", fabs( ans ) + eps );
	}
	return 0;
}

Ancient Berland Circus

#include <cmath>
#include <cstdio>
#define eps 1e-2
double pi = acos( -1.0 );
struct point {
	double x, y;
}p[3];
double len[3], rad[3];

double gcd( double x, double y ) {
	if( fabs( y ) < eps ) return x;
	else if( fabs( x ) < eps ) return y;
	else return gcd( y, fmod( x, y ) );
}

double dis( int i, int j ) {
	return sqrt( ( p[i].x - p[j].x ) * ( p[i].x - p[j].x ) + ( p[i].y - p[j].y ) * ( p[i].y - p[j].y ) );
}

int main() {
	for( int i = 0;i < 3;i ++ )
		scanf( "%lf %lf", &p[i].x, &p[i].y );
	double C = 0;
	for( int i = 0;i < 3;C += len[i], i ++ )
		len[i] = dis( i, ( i + 1 ) % 3 );
	C /= 2;
	double S = sqrt( C * ( C - len[0] ) * ( C - len[1] ) * ( C - len[2] ) );
	double R = len[0] * len[1] * len[2] / ( 4 * S );
	for( int i = 0;i < 2;i ++ )
		rad[i] = acos( 1 - len[i] * len[i] / ( 2 * R * R ) );
	rad[2] = 2 * pi - rad[0] - rad[1];
	double e = gcd( rad[0], gcd( rad[1], rad[2] ) );
	printf( "%.6f\n", pi * R * R * sin( e ) / e );
	return 0;
}

Open-air shopping malls

problem

枚举圆心,二分半径,然后求与每个圆相交面积,是否达到一半

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define eps 1e-10
#define maxn 25
int T, n;

double pi = acos( -1.0 );

int dcmp( double x ) {
	return fabs( x ) < eps ? 0 : ( x > 0 ? 1 : -1 );
}

struct point {
	double x, y;
	point(){}
	point( double X, double Y ) { x = X, y = Y; }
	friend double dis( point p1, point p2 ) { return sqrt( ( p1.x - p2.x ) * ( p1.x - p2.x ) + ( p1.y - p2.y ) * ( p1.y - p2.y ) ); }
};

struct circle {
	point o; double r;
	circle(){}
	circle( point O, double R ) { o = O, r = R; }
}C[maxn];

double area_circle_intersect( circle c1, circle c2 ) {
	double d = dis( c1.o, c2.o );
	if( dcmp( d - c1.r - c2.r ) >= 0 ) return 0;
	if( dcmp( d - fabs( c1.r - c2.r ) ) <= 0 ) {
		double r = min( c1.r, c2.r );
		return pi * r * r;
	}
	double rad1 = acos( ( c1.r * c1.r + d * d - c2.r * c2.r ) / ( 2 * c1.r * d ) ); 
	double rad2 = acos( ( c2.r * c2.r + d * d - c1.r * c1.r ) / ( 2 * c2.r * d ) );
	return rad1 * c1.r * c1.r + rad2 * c2.r * c2.r - c1.r * d * sin( rad1 );
}

bool check( circle c ) {
	for( int i = 1;i <= n;i ++ )
		if( dcmp( area_circle_intersect( c, C[i] ) * 2 - pi * C[i].r * C[i].r ) < 0 )
			return 0;
	return 1;
}

double solve( double l, double r, circle c ) {
	double ans;
	while( fabs( r - l ) > eps ) {
		double mid = ( l + r ) / 2;
		c.r = mid;
		if( check( c ) ) ans = mid, r = mid;
		else l = mid;
	}
	return ans;
}

int main() {
	scanf( "%d", &T );
	while( T -- ) {
		scanf( "%d", &n );
		for( int i = 1;i <= n;i ++ )
			scanf( "%lf %lf %lf", &C[i].o.x, &C[i].o.y, &C[i].r );
		double ans = 1e18;
		for( int i = 1;i <= n;i ++ ) {
			double l = 0, r = 0;
			for( int j = 1;j <= n;j ++ )
				r = max( r, C[j].r + dis( C[i].o, C[j].o ) );
			ans = min( ans, solve( l, r, C[i] ) );
		}
		printf( "%.4f\n", ans );
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值