计算几何(二)

计算几何

1.https://codeforces.com/problemset/problem/40/A 放到第一象限再判断

int n,k;
struct Point {
	int x,y;
	int id;
	Point() {}
	Point(double x,double y):x(x),y(y) {}
	Point operator - (Point B) {
		return Point(x-B.x,y-B.y);
	}
	bool operator == (Point B) {
		return x == B.x && y == B.y;
	}
};

int Distance(Point A,Point B) {
//	return hypot(A.x-B.x,A.y-B.y);
	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

void work(){
	double x,y;
	scanf("%lf%lf",&x,&y);
	if(abs(x) < eps || abs(y) < eps){
		cout << "black" << endl;
		return ;
	}
	if(y < 0){
		x =  -x;
		y = -y;
	}
	int tt=0;
	if(x < 0){
		x = -x;
		tt=1;
	}
	
	int q=0;
	for(double i=0;;i+=1){
		if(fabs(i*i-x*x-y*y) < eps || fabs((i+1)*(i+1)-x*x-y*y) < eps){
			cout << "black" << endl;
			return ;
		}
		if(x*x+y*y > i*i && x*x+y*y < (i+1)*(i+1)){
			int t = (int)i;
			if(t&1)q=1;//白
			else q=0; 
			break;
		}
	}
	
	if(tt){
		q = 1-q;
	}
	if(q)cout << "white" << endl;
	else cout << "black" << endl;
	
}

2.https://codeforces.com/problemset/problem/614/C

一个多边形绕一个点旋转一周,问覆盖的面积

先坐标转化成绕原点,可以发现,找到距离圆心的最远点和最近点,形成的圆环就是答案,然后最远的点一定是顶点,最近的可能是线段,要求点/线段到原点的距离.

const int N = 1e5 + 50;
const int INF = 0x7fffffff;
const double eps = 1e-9;
const double PI = acos(-1);

int sgn(double x) {
	if(fabs(x) < eps)return 0;
	else return x<0?-1:1;
}

struct Point {
	double x,y;
	Point() {}
	Point(double x,double y):x(x),y(y) {}
	Point operator - (Point B) {
		return Point(x-B.x,y-B.y);
	}
	bool operator == (Point B) {
		return x == B.x && y == B.y;
	}
};

struct Line {
	Point p1,p2;//线上的两个点
	Line() {}
	Line(Point p1,Point p2):p1(p1),p2(p2) {}
};


double Distance(Point A,Point B) {
	return hypot(A.x-B.x,A.y-B.y);
//	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

double Cross(Point a,Point b) {
	return a.x*b.y-a.y*b.x;
}

int n;
Point o,p[N];
typedef Point Vector;
typedef Line Segment;
double Dot(Vector A,Vector B) {
	return A.x*B.x + A.y*B.y;
}


//点到直线的距离
double Dis_point_line(Point p, Line v) {
	return fabs(Cross(p-v.p1,v.p2-v.p1))/Distance(v.p1,v.p2);
}

//点到线段的距离
double Dis_point_seg(Point p, Segment v) {
	if(sgn(Dot(p- v.p1,v.p2-v.p1))<0 || sgn(Dot(p- v.p2,v.p1-v.p2))<0)
		return min(Distance(p,v.p1),Distance(p,v.p2));
	return Dis_point_line(p,v); //点的投影在线段上
}

void work() {
	scanf("%d%lf%lf",&n,&o.x,&o.y);
	double maxn=0,minx = INF;
	Point z=Point(0,0);
	for(int i=0; i<n; i++) {
		scanf("%lf%lf",&p[i].x,&p[i].y);
		p[i] = p[i] - o;
		maxn=max(maxn,Distance(p[i],z));
		minx=min(minx,Distance(p[i],z));
	}
	p[n] = p[0];
	for(int i=1; i<=n; i++) {
		minx = min(minx,Dis_point_seg(z,Line(p[i],p[i-1])));
//		printf("%d ----- %lf
",i,Dis_point_seg(z,Line(p[i],p[i-1])));
	}

//	cout << minx << " " << maxn << endl;

	double ans = PI * (maxn*maxn - minx*minx);
	printf("%.8f
",ans);
}

3.https://codeforces.com/problemset/problem/667/A 水题

double d,h,v,e;

void work(){
	scanf("%lf%lf%lf%lf",&d,&h,&v,&e);
	v /= PI*(d/2.0)*(d/2.0);
	double hh = v;
	if(h + e*100000 > hh * 100000)printf("NO
");
	else {
		double t = h / (hh-e);
		printf("YES
");
		printf("%.6f
",t);
	}
}

4.https://codeforces.com/problemset/problem/672/C

由于中间的路都是点到原点的距离,那么分三种情况:

1)只有一个人在走,那就只有一段Dis(第一次遇到的点,A或B)

2)两个人都在走,有两段不完整的. 用la,lb,lt表示,只有A动,只有b动,a和b都动的情况,具体看注释

struct Point {
	double x,y;
	Point() {}
	Point(double x,double y):x(x),y(y) {}
	Point operator - (Point B) {
		return Point(x-B.x,y-B.y);
	}
	bool operator == (Point B) {
		return x == B.x && y == B.y;
	}
};

double Distance(Point A,Point B) {
	return hypot(A.x-B.x,A.y-B.y);
//	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
}

Point A,B,o;
int n;
Point p[N];

void work() {
	scanf("%lf%lf%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y,&o.x,&o.y);
	scanf("%d",&n);
	
	for(int i=0; i<n; i++) {
		scanf("%lf%lf",&p[i].x,&p[i].y);
	}
	double la=Distance(p[0],A)+Distance(p[0],o);   //当前只有A动
	double lb=Distance(p[0],B)+Distance(p[0],o);   //当前只有B动
	double lt=min(la,lb);   //两个都动
	double sum=Distance(p[0],o)*2;   //记录走过前i个点的长度
	
	for(int i=1;i<n;i++){
		double nl = Distance(p[i],o); 
        //AB都走 = Min{前i-1个只有a动,当前B动 || 前i-1个只有b动,当前A动 || 之前两个都动,当前不动}
		lt = min(min(la + Distance(p[i],B)+nl,lb+Distance(p[i],A)+nl),lt+2*nl);
		//a走 = Min{之前用过机会了,当前走完整 || 之前的完整+当前不完整}
		la = min(la+2*nl,sum+Distance(p[i],A)+nl);
		lb = min(lb+2*nl,sum+Distance(p[i],B)+nl);
		sum += 2*nl;
	}
	printf("%.8f
",min(min(la,lb),lt));
	
}

原文地址:https://www.cnblogs.com/LaiYiC/p/15027979.html