Codeforces Round #357 (Div. 2) E 计算几何

传说中做cf不补题等于没做 于是第一次补...这次的cf没有做出来DE D题的描述神奇 到现在也没有看懂 于是只补了E

每次div2都是hack前2~3题 终于打出一次hack后的三题了...希望以后能越来越好 早日..至少变成蓝色名字吧:)

E题意 有一个蟑螂 人要打死它 给出蟑螂的坐标 速度 人的瞄准时间 再给出一些阴影(圆形且给出坐标与半径) 若蟑螂移动到阴影内会立即停下 人不能打到阴影中的蟑螂 问它不被打死的机率 蟑螂的移动方向是随机的

需要注意的是蟑螂只会朝一个方向走直线

所以我们对于每一个阴影圆 都判断一次 能否走到 如果能走到 就计算角度 这里利用atan来实现 atan(x,y) 返回的是平面直角坐标系上原点到x,y的线与x轴的夹角

需要注意的是 在两个圆的相交到一定程度的时候需要进行判断 是否到了最大值 在到达最大值之后 角度会减小 这时候应当取最大的角度

对于每一个可以到达的阴影 我们都可以得出一个角度区间 最后我们应当对每个区间进行合并

在angle+-ang之后 可能产生<-pi or >pi的角度 这时候我们进行分割 分成两份 一份在最左 一份在最右

排个序再进行判断就好

在补这道题的时候 acos的时候写错了字母...一路跑到了test79才wa掉...真是..doubility

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<queue>
using namespace std;
double x0,yy,v,t;
int n;
double pi;
struct node
{
    double x,y,r;
};
node a[100050];
int w;
struct no
{
    double k1,k2;
};
no b[100050];
double dis(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double r;
void check(int x){
    if(dis(a[x].x,a[x].y,x0,yy)>=(r+a[x].r))
        return ;
    double d=dis(a[x].x,a[x].y,x0,yy);
    /// -pi<angel<pi
    double angle=atan2(a[x].x-x0,a[x].y-yy);
    double r1=sqrt(d*d-a[x].r*a[x].r);
    double ang;
    if(r1<r){
        ang=asin(a[x].r/d);
    }
    else {
        ang=acos((d*d+r*r-a[x].r*a[x].r)/(2*d*r));
    }
    double al=angle-ang;
    double ar=angle+ang;
    if(al>=-pi-0.000000000001&&ar<=pi+0.000000000001){
        w++;
        b[w].k1=al;
        b[w].k2=ar;
    }
    else if(al<-pi-0.000000000001){
        w++;
        b[w].k1=-pi;
        b[w].k2=ar;
        w++;
        b[w].k1=pi+(al+pi);
        b[w].k2=pi;
    }
    else if(ar>pi+0.000000000001){
        w++;
        b[w].k1=al;
        b[w].k2=pi;
        w++;
        b[w].k1=-pi;
        b[w].k2=-pi+(ar-pi);
    }
    return ;
}
int cmp(no a,no b){
    return a.k1<b.k1;
    return a.k2>b.k2;
}
int main(){
while(cin>>x0>>yy>>v>>t){
    pi=acos(-1);
    cin>>n;
    bool ok=false;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].r);
        if((x0-a[i].x)*(x0-a[i].x)+(yy-a[i].y)*(yy-a[i].y)<=a[i].r*a[i].r){
            ok=true;
        }
    }
    r=v*t;
    if(ok==true){
        printf("1.00000000000\n");
    }
    else {
        w=0;
        for(int i=1;i<=n;i++){
            check(i);
        }
        if(w==0)
        {
            printf("0.00000000000\n");
        }
        else {
            sort(b+1,b+1+w,cmp);
            double ans=0;
            double q=-pi;
            for(int i=1;i<=w;i++)
            {
                double l=b[i].k1;
                double r=b[i].k2;
                if(r>q){
                    double ll;
                    if(l>q){
                        ll=l;
                    }
                    else {
                        ll=q;
                    }
                    if(r-ll>0)
                    ans+=(r-ll);
                    q=r;
                }
                else continue;
            }
            printf("%.11f\n",ans/(2*pi));
        }
    }

}
}

  

时间: 2024-08-09 02:05:32

Codeforces Round #357 (Div. 2) E 计算几何的相关文章

Codeforces Round #357 (Div. 2) - C - Heap Operations

WA * 3 + TLE *1  啊啊啊!说好的考虑问题要仔细呢?! 题意: 简单说就是,有一串操作,丢失了一部分,只有 n 个操作了, 补全操作,使得每次 getMin 得到对应的值.输出所有操作的个数和操作序列. 解题: 用优先队列直接模拟过来的,标记一下某些位置 表示它之前还要进行哪些操作 才能做到,最后直接输出:对于每个情况,如果是 removeMin , 考虑队列是否为空,如果空,就要先插入一个::如果是 getMin ,考虑 当前队列最小的元素 比 给出的数 大还是小,如果小的话要把

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/

Codeforces Round #198 (Div. 2)A,B题解

Codeforces Round #198 (Div. 2) 昨天看到奋斗群的群赛,好奇的去做了一下, 大概花了3个小时Ak,我大概可以退役了吧 那下面来稍微总结一下 A. The Wall Iahub and his friend Floyd have started painting a wall. Iahub is painting the wall red and Floyd is painting it pink. You can consider the wall being mad

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除

Codeforces Round #339 (Div. 2) B. Gena&#39;s Code

B. Gena's Code It's the year 4527 and the tanks game that we all know and love still exists. There also exists Great Gena's code, written in 2016. The problem this code solves is: given the number of tanks that go into the battle from each country, f