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



链接:戳这里


E. Runaway to a Shadow
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Dima is living in a dormitory, as well as some cockroaches.

At the moment 0 Dima saw a cockroach running on a table and decided to kill it. Dima needs exactly T seconds for aiming, and after that he will precisely strike the cockroach and finish it.

To survive the cockroach has to run into a shadow, cast by round plates standing on the table, in T seconds. Shadow casted by any of the plates has the shape of a circle. Shadow circles may intersect, nest or overlap arbitrarily.

The cockroach uses the following strategy: first he equiprobably picks a direction to run towards and then runs towards it with the constant speed v. If at some moment t ≤ T it reaches any shadow circle, it immediately stops in the shadow and thus will stay alive. Otherwise the cockroach is killed by the Dima's precise strike. Consider that the Dima's precise strike is instant.

Determine the probability of that the cockroach will stay alive.

Input
In the first line of the input the four integers x0, y0, v, T (|x0|, |y0| ≤ 109, 0 ≤ v, T ≤ 109) are given — the cockroach initial position on the table in the Cartesian system at the moment 0, the cockroach's constant speed and the time in seconds Dima needs for aiming respectively.

In the next line the only number n (1 ≤ n ≤ 100 000) is given — the number of shadow circles casted by plates.

In the next n lines shadow circle description is given: the ith of them consists of three integers xi, yi, ri (|xi|, |yi| ≤ 109, 0 ≤ r ≤ 109) — the ith shadow circle on-table position in the Cartesian system and its radius respectively.

Consider that the table is big enough for the cockroach not to run to the table edges and avoid Dima's precise strike.

Output
Print the only real number p — the probability of that the cockroach will stay alive.

Your answer will be considered correct if its absolute or relative error does not exceed 10 - 4.

Examples
input
0 0 1 1
3
1 1 1
-1 -1 1
-2 2 1
output
0.50000000000
input
0 0 1 0
1
1 0 1
output
1.00000000000
Note
The picture for the first sample is given below.
Red color stands for points which being chosen as the cockroach's running direction will cause him being killed, green color for those standing for survival directions. Please note that despite containing a circle centered in ( - 2, 2) a part of zone is colored red because the cockroach is not able to reach it in one second.


题意:

一只蟑螂在T秒内以速度v朝着任意方向跑到阴影部分去,阴影部分全都是圆组成。问蟑螂存活的概率。


思路:

蟑螂在T秒内逃跑的范围是一个圆,所以只需要判断圆与阴影部分相交范围。

1:当圆与阴影部分不相交则跑不到。

2:阴影部分在圆内或者大于一半的圆

3:圆在阴影部分内


这里需要注意用long double 更好处理精度,还有就是正数会超int

我一直wa一个地方,跟我平时的习惯有关,就是出来精度的时候没有去考虑进度需不需要加上去

在判断圆在阴影部分内的时候,应该严格的在里面。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
struct circle{
    ll x,y,r;
}C[100100];
ll X,Y,V,T,R;
int n;
const long double eps=1e-8;
const long double pi=acos(-1.0);
int dcmp(long double x){
    if(fabs(x)<=eps) return 0;
    return x<0?-1:1;
}
vector<pair<long double,int> > ans;
int flag=0;
void solve(circle c){
    long double dis=sqrt((long double)(c.x-X)*(c.x-X)+(long double)(c.y-Y)*(c.y-Y));
    if(dis<=c.r) {
        flag=1;
        return ;
    }
    if(dcmp(dis-c.r-R)>=0) return ;
    long double angO=atan2(c.y-Y,c.x-X);
    if(dcmp(angO)<0) angO+=2*pi;
    long double d=sqrt(dis*dis-c.r*c.r);
    long double ang;
    if(dcmp(R-d)>=0){
        ang=asin(c.r/dis);
    } else {
        ang=acos((R*R+dis*dis-c.r*c.r)/(2.0*dis*R));
    }
    long double ang1=angO-ang;
    long double ang2=angO+ang;
    if(dcmp(ang1)<0){
        ang1+=2.0*pi;
        ans.push_back(make_pair(ang1,1));
        ans.push_back(make_pair(2*pi,-1));
        ans.push_back(make_pair(0.0,1));
        ans.push_back(make_pair(ang2,-1));
    } else if(dcmp(ang2-2*pi)>0){
        ang2-=2.0*pi;
        ans.push_back(make_pair(ang1,1));
        ans.push_back(make_pair(2*pi,-1));
        ans.push_back(make_pair(0.0,1));
        ans.push_back(make_pair(ang2,-1));
    } else {
        ans.push_back(make_pair(ang1,1));
        ans.push_back(make_pair(ang2,-1));
    }
}
int main(){
    scanf("%I64d%I64d%I64d%I64d",&X,&Y,&V,&T);
    scanf("%d",&n);
    R=V*T;
    for(int i=1;i<=n;i++) {
        scanf("%I64d%I64d%I64d",&C[i].x,&C[i].y,&C[i].r);
    }
    for(int i=1;i<=n;i++){
        solve(C[i]);
        if(flag){
            printf("1.00000000000\n");
            return 0;
        }
    }
    sort(ans.begin(),ans.end());
    int now=0,last=0,tmp=0;
    long double sum=0.0;
    for(int i=0;i<ans.size();i++){
        tmp+=ans[i].second;
        now=i;
        if(tmp==0){
            sum+=ans[now].first-ans[last].first;
            last=now+1;
        }
    }
    cout<<setprecision(11)<<sum/(2.0*pi)<<endl;
    return 0;
}
/*
0 0 1 1
1
1 1000000000 1000000000
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值