BUPT Summer Journey #test2 E

時間限制 1000 ms內存限制 65536 KB

題目描述

木頭人星的行動速度是地球上烏龜的1/10 (所以可以忽略移動的速度),可是他們也熱愛運動,尤其是足球。 他們的足球規則跟人類的一樣,足球場尺寸爲標準 105 * 68,兩隊各 11 名球員參賽。 假設 Mays 隊的每個隊員都是專業的球員,踢球都特別準。而她們的對手 Luke 隊截球的規律是,如果行進的球離自己的距離不超過d ,就可以截球成功。 現在 Mays 隊的十號球員拿到了球,如果只允許一次射門,Mays 隊能不能進球呢? 足球場在xy 平面內,(0,0)至(105,68)矩形範圍內,邊緣與x,y 軸平行且不能站人。其中Luke隊的球門爲(0, 30)-(0, 38),Mays 隊的球門爲(105,30)-(105, 38)

輸入格式

第一行爲組數T  ,對這T 組數據,每組第一行是Mays隊十號球員的座標x 0 ,y 0  ,接下來 11 行爲 Luke 隊的 1 - 11 號隊員的屬性 x i ,y i ,d i  , 其中x i ,y i  表示 i 號球員的座標,d i  表示i 號球員截球能力值。 保證所有座標不重複且都在球場範圍內,x,y 爲整數,d 爲正實數1.0d3.0 

輸出格式

每組數據一行,如果 Mays 隊10號隊員直接可以射門得分,則輸出“Shoot!‍‍”;如果10號隊員不能成功射門,輸出"Poor Mays!‍‍".

輸入樣例

1
104 34
1 24 2.928
48 25 2.605
15 41 1.312
39 42 2.454
3 12 2.080
18 39 1.564
10 36 2.530
97 13 1.589
101 57 1.844
84 39 2.561
0 33 1.831‍

輸出樣例

Shoot!
思路:一開始想用斜率算。然後轉化爲斜率的區間覆蓋問題。但是存在着很多特判。例如:如果其夾角大於90度的時候它的斜率會變爲負,比如他90度的時候又如何算。然後我處理特判的情況又會影響到我一般情況的判斷。後來轉化成角度問題。以射門10號球員的正下方爲0度角,若theta=atan2(Luke[i].y-yo,Luke[i].x-xo)爲正,則theta=-theta-90,若theta=atan2(Luke[i].y-yo,Luke[i].x-xo)爲負,則theta=270-theta.然後先預處理每個luke球員與10號球員的距離,若小於等於d則會被攔下直接輸Poor Mays!若不然再處理每個球員的角度區間[Luke[i].AngleDown,Luke[i].AngleUp],按左端點爲關鍵字即降序排序,然後若球員干擾角度區間[Luke[i].AngleDown,Luke[i].AngleUp]在射門區間[AngleDown,AngleUp]外面不相交則不考慮,若在中間的話若當前的Luke[i].AngleDown大於之間區間合併Luke[i].AngleUp的最大值則存在射門空隙直接break判shoot!否則循環出去後判斷它的最大值Luke[i].AngleUp是否超過AngleUp若超過則shoot!若超不過則Poor Mays!

代碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
//#define LOCAL
using namespace std;
struct point
{
    double x,y,d,AngleUp,AngleDown;
}Luke[20];
struct PP
{
    double x,y;
}UnCovered[20];
const double eps=1e-7;
const double pi=acos(-1.0);
double xo,yo,AngleUp,AngleDown;
int negativecnt;
bool flag;
bool GetLukeAngle(int x)
{
    int i;
    double d=sqrt((xo-Luke[x].x)*(xo-Luke[x].x)+(yo-Luke[x].y)*(yo-Luke[x].y));
    if(abs(Luke[x].d-d)<eps)return false;
    double a=asin(Luke[x].d/d),b;
    double dy=Luke[x].y-yo,dx=Luke[x].x-xo;
    b=atan2(dy,dx);
    if(b>eps)b=3*pi/2-b;
    else if(b<-eps)b=-pi/2-b;
    else b=pi*3/2;
    Luke[x].AngleDown=b-a;
    Luke[x].AngleUp=b+a;
    return true;
}
bool cmp(const point &a,const point &b)
{
    if(abs(a.AngleDown-b.AngleDown)<eps)return a.AngleUp+eps<b.AngleUp;
    return a.AngleDown+eps<b.AngleDown;
}
void Init()
{
    scanf("%lf%lf",&xo,&yo);
    AngleUp=atan2(38.000-yo,-xo);
    if(AngleUp<-eps)AngleUp=-AngleUp-pi/2;
    else if(AngleUp>eps) AngleUp=pi*3/2-AngleUp;
    AngleDown=atan2(30.000-yo,-xo);
    if(AngleDown<-eps)AngleDown=-AngleDown-pi/2;
    else if(AngleDown>eps) AngleDown=pi*3/2-AngleDown;
    flag=true;
    for(int i=1;i<=11;i++)
    {
        scanf("%lf %lf %lf",&Luke[i].x,&Luke[i].y,&Luke[i].d);
        if(flag==true)flag=GetLukeAngle(i);
        else break;
    }
}
void Solve()
{
    sort(Luke+1,Luke+1+11,cmp);
    flag=false;
    double start=AngleDown;
    for(int i=1;i<=11;i++)
    {
            if(Luke[i].AngleUp+eps<AngleDown)continue;
            if(Luke[i].AngleDown>AngleUp+eps)continue;
            if(Luke[i].AngleDown>start+eps)
            {
                flag=true;break;
            }
            else if(Luke[i].AngleUp>start+eps)start=Luke[i].AngleUp;
    }
    if(flag==false&&start+eps<AngleUp)flag=true;
}
int main()
{
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    #endif // LOCAL
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        if(flag==true)Solve();
        if(flag)printf("Shoot!\n");
        else printf("Poor Mays!\n");
    }
    return 0;
}


 

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