1. 程式人生 > >打籃球 ( pass ) 圖論

打籃球 ( pass ) 圖論

space 2.6 防禦 關於 精確 left 容易 str 成功

【題目描述】 信息組的同學是比較喜歡打籃球的。 喜歡打籃球的同學很容易發現傳球在籃球運動中是非常重要的,球傳的好也就意味著球 打的順。經常傳球雖然不一定保證 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 ) 圖論