打籃球 ( pass ) 圖論
阿新 • • 發佈:2017-08-25
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 namespacestd; 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 ) 圖論