An Easy Physics Problem HDU - 5572 直线与圆

//#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 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;
	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;
	}
	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 circle{
	Point p;
	double r;
	circle(Point _p,double _r){
		p=_p;r=_r;
	}
	int relationline(Line v){
		double dst=v.dispointtoline(p);
		if(sgn(dst-r)<0)return 2;
		else if(sgn(dst-r)==0)return 1;
		return 0;
	}
	int relationseg(Line v){
		double dst=v.dispointtoseg(p);
		if(sgn(dst-r)<0)return 2;
		else if(sgn(dst-r)==0)return 1;
		return 0;
	}
	int pointcrossline(Line v,Point &p1,Point &p2){
		if(!(*this).relationline(v))return 0;
		Point a=v.lineprog(p);
		double d=v.dispointtoline(p);
		d=sqrt(r*r-d*d);
		if(sgn(d)==0){
			p1=a;p2=a;return 1;
		}
		p1=a+(v.e-v.s).trunc(d);
		p2=a-(v.e-v.s).trunc(d);
		return 2;
	}
};

int check(Point A,Point B,Point C){
	if(B.x==C.x){
		if((B.y-C.y)*(A.y-C.y)<0)return 1;
		return 0;
	}else if(B.y==C.y){
		if( (B.x-C.x)*(A.x-C.x)<0)return 1;
		return 0;
	}
	if( (B.x-C.x)*(A.x-C.x)<0 )return 1;
	return 0;
}


int main(){
	int T;
	scanf("%d",&T);
	int kase=0;
	while(T--){
		double x,y,r;
		scanf("%lf%lf%lf",&x,&y,&r);
		Point yuanxin=Point(x,y);
		circle yuan=circle(yuanxin,r);		//圆柱 yuan
		
		Point A;
		scanf("%lf%lf",&x,&y);A=Point(x,y);	//源点 A
		double vx,vy;scanf("%lf%lf",&vx,&vy);
		Line l1;
		Point to;to=Point(vx+x,vy+y);
		l1=Line(A,to);						//初始直线 l1

		double bx,by;scanf("%lf%lf",&bx,&by);
		Point B=Point(bx,by);				//终端 B

		Point p1,p2;
		
		int xiangjiao=0;
		xiangjiao=yuan.pointcrossline(l1,p1,p2);
		
		printf("Case #%d: ",++kase);

		if(!xiangjiao){
			if(fabs(l1.dispointtoline(B))<eps){
			
				if(int(B.x-A.x)*int(vy)==int(B.y-A.y)*int(vx)){
					printf("Yes\n");
				}else{
					printf("No\n");
				}
				continue;
			}else printf("No\n");
		}else{	
			//路径直线香蕉
			//p1,p2是两个直线与圆的交点
			//要靠近A的交点

			Point bounce;
			double dis1=(A.x-p1.x)*(A.x-p1.x)+(A.y-p1.y)*(A.y-p1.y);
			double dis2=(A.x-p2.x)*(A.x-p2.x)+(A.y-p2.y)*(A.y-p2.y);
			if(dis1<dis2)bounce=p1;else bounce=p2;				

			Point C=bounce;
			
			int way=1;//速度指向圆

			if(vx==0){
				if( (C.y-A.y)*vy<0 )way=0;
			}else if(vy==0){
				if( (C.x-A.x)*vx<0)way=0;
			}else{
				if( (C.x-A.x)*vx<0 || (C.y-A.y)*vy<0)way=0;
			}
		//	cout<<way<<endl;
			if(way==1){		//会反弹
				
				Line l2=Line(B,bounce);
	
				if(fabs(l1.dispointtoline(B))<eps){			

					if(check(A,B,C)){
						printf("No\n");
						continue;
					}else{
						printf("Yes\n");
						continue;
					}
				}else{			
					if(yuan.relationseg(l2)>=2){
						printf("No\n");
						continue;
					}
					

					double d1=l1.dispointtoline(yuanxin);
					double d2=l2.dispointtoline(yuanxin);

					if(fabs(d1-d2)<eps){	//两个直线镜面
						printf("Yes\n");
					}else printf("No\n");
				}

			}else{
				if(fabs(l1.dispointtoline(B))<eps){	
					if(int(B.x-A.x)*int(vy)==int(B.y-A.y)*int(vx)){
						printf("Yes\n");
					}else{
						printf("No\n");
					}
					continue;
				}else printf("No\n");
			}
		}
	}
}

QAQ !

第一发计算几何题,WA5小时才过去

自己的几何能力还是过得去的,很快想出了最复杂情况的做法

(敲的时候把脑内秒过的简单情况给忘了QAQ

不过因为第一次用模板,接口不熟,把自己坑爆了

刚几何!

posted @ 2017-07-19 20:50  Drenight  阅读(177)  评论(0编辑  收藏  举报