码迷,mamicode.com
首页 > 其他好文 > 详细

打篮球 ( pass ) 图论

时间:2017-08-26 04:44:33      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:double   nsf   一个   using   spfa   移动   pen   stdin   5.7   

【题目描述】
信息组的同学是比较喜欢打篮球的。
喜欢打篮球的同学很容易发现传球在篮球运动中是非常重要的,球传的好也就意味着球
打的顺。经常传球虽然不一定保证
100%
概率进球,但是总归是使球场气氛更加活跃了。
现在我们来看一场篮球比赛,肉蟹队vs宇宙大总统队。每支队伍都有N个(肉蟹)或(宇宙大总统),现在轮到肉蟹队进攻。比赛可以看成在一个无限大的二维平面上进行,每个球员都有一个坐标篮筐也有一个坐标(50,0)。肉蟹们进攻的方式就是先传球若干次,再投篮。
一旦投篮,这一轮进攻就立即结束。
由于有宇宙大总统们的防御,所以肉蟹们传球和投篮都是有成功率的。
传球和投篮的轨迹可以看成一条线段。
关于传球和投篮的成功率如下:
传球:
Cp*(1-(ls/150)^2)*dr/(dr+1)
投篮:
(Cs*dr/(dr+1))^ln(ls)
其中
Cp和Cs
是给定的常数,ls是球的运动轨迹的长度,dr是防御队员的干扰系数,
由于宇宙大总统非常有智慧,所以大总统们知道他们既可以干扰传球的,也可以干扰接球的,既可以盖帽,也可以干扰球(这里干扰球不算犯规),因此dr就等于所有宇宙大总统到球运动轨迹两端点距离的最小值。
肉蟹们知道直接与宇宙大总统对抗是没有胜算的,所以她们对球场施了一个神秘的魔法,使得场上的所有人都瞬间变肉,以至于无法移动。
现在球在第一个肉蟹手上,请你设计一个传球和投篮的方案。求肉蟹们在这一轮就进球的概率最大是多少。
【输入数据】
第一行三个数,分别表示
N,Cp,Cs
接下来N行,每行两个数,表示肉蟹们的坐标
接下来N行,每行两个数,表示宇宙大总统们的坐标
【输出数据】
一行,一个数,即最大的概率。
精确到小数点后6位。
【输入样例1】
3 1 1
50 50
35 60
70 15
75 5
72 25
45 17
【输出样例1】
0.806732
【输入样例2】
1 0.5 0.5
50 4
50 3
【输出样例2】
0.146342
【输入样例3】
5 0.999999 0.8
50 50
40 50
40 40
40 30
50 20
50 41
44 29
48
27
45 41
48 64
【输出样例3】0.294171
【数据约定】
30%:1≤N≤ 5100%:1≤N≤ 500≤坐标≤ 1000≤Cp,Cs≤ 1
这题其实可以用DP和最短路做,我选择的是最短路。
我们只需预处理一些数据,然后就可以跑一遍spfa,然后在一一和篮筐判定选出答案就可以了。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
int n;
db cp,cs;
struct rou
{
    db x,y;
}r[145];
struct tong
{
    db x,y;
}t[145];
il db distance(db x1,db y1,db x2,db y2)
{
    db r1=x2-x1,r2=y2-y1;
    return (db)sqrt(r1*r1+r2*r2);
}
db dist1[145][145];
db dist2[145][145];
db dist[145];
db lan[145];
db gan[145];
db minx=9999;
bool vis[145];
il void spfa()
{
    int t[145];
    int head=0,tail=1;
    t[0]=1;
    dist[1]=1;
    while(head!=tail)
    {
        int h=t[head++];
        vis[h]=0;
        for(int i=1;i<=n;i++)
        {
            db ls=dist1[h][i],dr=min(gan[h],gan[i]);
            if(dist[i]<dist[h]*(cp*(1-(ls/150)*(ls/150))*(dr/(dr+1))))
            {
                dist[i]=dist[h]*(cp*(1-(ls/150)*(ls/150))*(dr/(dr+1)));
                if(!vis[i])
                {
                    vis[i]=1;
                    t[tail++]=i;
                }
            }
        }
    }
}
int main()
{
    freopen("pass.in","r",stdin);
    freopen("pass.out","w",stdout);
    cin>>n>>cp>>cs;
    for(int i=1;i<=n;i++)
    cin>>r[i].x>>r[i].y;
    for(int i=1;i<=n;i++)
    cin>>t[i].x>>t[i].y;
    for(int i=1;i<=n;i++)
    lan[i]=distance(r[i].x,r[i].y,50.0,0);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            dist1[i][j]=dist1[j][i]=distance(r[i].x,r[i].y,r[j].x,r[j].y);
            dist2[i][j]=distance(r[i].x,r[i].y,t[j].x,t[j].y);
        }
    for(int i=1;i<=n;i++)
    gan[i]=9999;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            gan[i]=min(gan[i],dist2[i][j]);
    for(int i=1;i<=n;i++)
        minx=min(minx,distance(t[i].x,t[i].y,50.0,0));
    spfa();
    db ans=0;
    for(int i=1;i<=n;i++)
    {
        db dr=min(minx,gan[i]);
        ans=max(ans,dist[i]*(pow((cs*dr/(dr+1)),(log(lan[i])))));
    }
    printf("%f\n",ans);
    return 0;
}

 

打篮球 ( pass ) 图论

标签:double   nsf   一个   using   spfa   移动   pen   stdin   5.7   

原文地址:http://www.cnblogs.com/gshdyjz/p/7429794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!