XMU 1071 聖鬥士黃金十二宮(七)銀河星爆 【計算幾何】

1071: 聖鬥士黃金十二宮(七)銀河星爆

Time Limit: 500 MS  Memory Limit: 64 MB
Submit: 193  Solved: 10
[Submit][Status][Web Board]

Description

  撒加回答了星矢的第一個問題,但是當星矢要問第二個問題時,撒加的頭髮全變白了。白撒加的實力是無人能及的,星矢被廢去了五感。這時幫沙加統計完單詞的一輝也趕到了,想打贏白撒加是不可能的,一輝的目標就是爭取時間讓星矢拿到銅盾。爲了儘快打倒被稱爲不死鳥的一輝,撒加也使出生平絕技---即使是星星被擊中也要粉碎的銀河星爆。
從撒加放出銀河星爆到銀河星爆接近一輝需要一段時間,在這段時間裏一輝可以朝任何方向移動k單位的距離來躲開銀河星爆。銀河星爆的橫截面爲一個圓形,顯然一輝在與橫截面平行的平面上移動可以以最大的概率躲過。在該平面上建立直角座標系橫軸爲x縱軸爲y,銀河星爆的橫截面圓心座標爲(x1, y1),半徑爲R1。
把一輝也當成一個圓,他在座標系上朝任意方向移動的最大距離爲k,考慮到地形因素和一輝個人能力,一輝所能移動到的點(x , y)需滿足0 <= x <= 1000 , 0 <= y <= 1000。如果兩個圓不相交則說明一輝躲過了銀河星爆(注意兩圓外切也說明一輝躲過了)。
現在請您預測一輝能否有可能躲過撒加的銀河星爆。

Input

  第一行爲三個整數x1, y1, R1,代表銀河星爆的圓心座標和半徑,其中0<= x1, y1 <= 1000, 0 < R1 <= 300。
第二行爲三個整數x2, y2, R2,代表一輝的圓心座標和半徑,其中0 <= x2, y2 <= 1000, 0 < R2 <= 30。
第三行爲一個正整數k <= 2000 表示一輝可以移動的最長距離。

Output

  如果一輝可以躲過銀河星爆則輸出"Yes",否則輸出"No"(不包含引號)。

Sample Input

900 900 250
950 950 30
316

Sample Output

Yes

HINT

Source

[Submit][Status][Web Board]


題目鏈接:

  http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1071

題目大意:

  一個炸彈,座標(X1,Y1),爆炸半徑R1,一個人,座標(X2,Y2),視爲球體半徑R2,人最多移動距離爲K,問能否躲過炸彈且圓心不超出邊界。(外切或相離)

題目思路:

  【計算幾何】

  首先將人的體積半徑算在爆炸範圍內,即R1=R1+R2。人的運動範圍也爲一個圓R2=K。這樣確定了兩個圓。

  分情況考慮,在不超界的情況下,如果相離或相切(圓心距離>=半徑和)則可行。

  如果相交,則優先考慮按圓心連線的方向逃離是否可行,是否超界。

  若超界則求圓的交點,若交點有一個在邊界內則可行。

  內含不可行。



/****************************************************

	Author : Coolxxx
	Copyright 2017 by Coolxxx. All rights reserved.
	BLOG : http://blog.csdn.net/u010568270

****************************************************/
#include<bits/stdc++.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define mem(a,b) memset(a,b,sizeof(a))
const double EPS=0.00001;
const int J=10;
const int MOD=100000007;
const int MAX=0x7f7f7f7f;
const double PI=3.14159265358979323;
const int N=124;
using namespace std;
typedef long long LL;
double anss;
LL aans;
int cas,cass;
int n,m,lll,ans;

struct Point
{
	double x, y;
	Point(double x = 0, double y = 0) :x(x), y(y) {}
};

typedef Point Vector;

Vector operator - (Point A, Point B)
{
	return Vector(A.x - B.x, A.y - B.y);
}

Vector operator + (Vector A, Vector B)
{
	return Vector(A.x + B.x, A.y + B.y);
}

Vector operator * (Vector A, double p)
{
	return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p)
{
	return Vector(A.x / p, A.y / p);
}

double Dot(Vector A,Vector B)
{
    return A.x * B.x + A.y * B.y;
}

double Length(Vector A)
{
    return sqrt(Dot(A,A));
}

double Angle(Vector A,Vector B)  //求角度
{
    return acos(Dot(A,B) / Length(A) / Length(B));
}

double angle(Vector v)
{
    return atan2(v.y,v.x);
}

const double eps = 1e-10;
int dcmp(double x)
{
    if(fabs(x) < eps) return 0;
    else
        return x < 0 ? -1 : 1;
}

bool operator < (const Point& a,const Point& b)
{
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}

bool operator == (const Point& a,const Point &b)
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

struct Circle
{
	Point c;
	double r;
	Circle(Point c, double r) :c(c), r(r) {}
	Point point(double a)
	{
		return Point(c.x + cos(a) * r, c.y + sin(a) * r);
	}
};

int getCircleCircleIntersection(Circle C1,Circle C2,vector<Point>& sol)  //求圓和圓的交點
{
    double d = Length(C1.c - C2.c);
    if(dcmp(d) == 0)   //首先圓心要重合
    {
        if(dcmp(C1.r - C2.r) == 0) return -1; //其次半徑要相同,然後就可以推出兩圓重合
        return 0;
    }
    if(dcmp(C1.r + C2.r - d) < 0) return 0; //相離沒交點
    if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; //圓在圓中,沒有交點

    double a = angle(C2.c - C1.c); //向量C1C2的極角
    double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); //C1C2到C1P1的角
    Point p1 = C1.point(a-da),p2 = C1.point(a+da);

    sol.push_back(p1);
    if(p1 == p2) return 1; //相切
    sol.push_back(p2);
    return 2; //相交
}
inline bool inside(double x,double y)
{
	return (x>=0 && x<=1000 && y>=0 && y<=1000);
}
int main()
{
	#ifndef ONLINE_JUDGE
	freopen("test10.in","r",stdin);
//	freopen("1.txt","w",stdout);
	#endif
	int i,j,k;
	double x,y,z;
	double xx,yy,zz;
//	for(scanf("%d",&cass);cass;cass--)
//	for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//	while(~scanf("%s",s))
	while(cin>>x>>y>>z)
	{
		cin>>xx>>yy>>zz>>k;
		Circle c1(Point(x,y),z+zz),c2(Point(xx,yy),k);
		
		if(dcmp(sqr(xx-x)+sqr(yy-y)-sqr(z+zz))>0)
		{
			puts("Yes");
			continue;
		}
		vector<Point>a;
		vector<Point>::iterator iter;
		while(!a.empty())a.pop_back();
		z=getCircleCircleIntersection(c1,c2,a);
		if(z == -1)
		{
			puts("Yes");
		}
		else if(z == 0)
		{
			double d = Length(c1.c - c2.c);
			if(dcmp(d) == 0)   //首先圓心要重合
			{
				if(dcmp(c1.r - c2.r) < 0)puts("Yes");
				else puts("No");
			}
			else if(dcmp(c1.r + c2.r - d) < 0)puts("Yes");//相離沒交點
			else if(dcmp(c2.r - c1.r - d) > 0)puts("Yes");//圓在圓中,沒有交點
			else puts("No");
		}
		else if(z == 1)
		{
			iter = a.begin();
			x = iter->x;
			y = iter->y;
			if(inside(x,y))puts("Yes");
			else puts("No");
		}
		else
		{
			x=c1.c.x+(c2.c.x-c1.c.x)*c1.r/(Length(c1.c-c2.c));
			y=c1.c.y+(c2.c.y-c1.c.y)*c1.r/(Length(c1.c-c2.c));
			if(sqr(x-c2.c.x)+sqr(y-c2.c.y)<=k*k && inside(x,y))
			{puts("Yes");continue;}
			
			iter = a.begin();
			x = iter->x;
			y = iter->y;
			iter++;
			xx = iter->x;
			yy = iter->y;
			if(inside(x,y) || inside(xx,yy))
				puts("Yes");
			else puts("No");
		}
	}
	return 0;
}
/*
//

//
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章