打篮球
【题目描述】
信息组的同学是比较喜欢打篮球的。
喜欢打篮球的同学很容易发现传球在篮球运动中是非常重要的,球传的好也就意味着球打的顺。经常传球虽然不一定保证 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 ≤ 5
100%:
1 ≤ N ≤ 50
0 ≤ 坐标 ≤ 100
0 ≤ Cp,Cs ≤ 1
这是一道图的考题,标程是用spfa构建最短路,然而我考试的时候一直在跑模拟,图想都没想到,直到看了题解……
题解
构图,最短路
本题只要照着题目要求构图然后用类似于最短路的方法求出球传到某个进攻球员的最大的概率f[i]即可。
这个最短路用SPFA即可。
因为数据比较水,所以我写的Floyed也过了代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n;
int cx[100], cy[100], ux[100], uy[100];
double cp, cs, maxx = 0;
double f[100][100];
double dr, g[100];
double doit2(double a) {
return a * a;
}
double doit1(int a, int b, int c, int d) {
return (sqrt(doit2(abs(a - c)) + doit2(abs(b - d))));
}
int main(){
freopen("Pass.in", "r", stdin);
freopen("Pass.out", "w", stdout);
scanf("%d %lf %lf", &n, &cp, &cs);
for (int i = 1; i <= n; ++i)
scanf("%d %d", &cx[i], &cy[i]);
for (int i = 1; i <= n; ++i)
scanf("%d %d", &ux[i], &uy[i]);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
dr = double(1 << 20);
for (int k = 1; k <= n; ++k)
if (min(doit1(cx[i], cy[i], ux[k], uy[k]), doit1(cx[j], cy[j], ux[k], uy[k])) < dr)
dr = min(doit1(cx[i], cy[i], ux[k], uy[k]), doit1(cx[j], cy[j], ux[k], uy[k]));
f[i][j] = cp * (1 - doit2(doit1(cx[i], cy[i], cx[j], cy[j]) / 150.0)) * dr / (dr + 1);
}
for (int i = 1; i <= n; ++i) {
dr = 1 << 20;
for (int j = 1; j <= n; ++j)
if (min(doit1(cx[i], cy[i], ux[j], uy[j]), doit1(ux[j], uy[j], 50, 0)) < dr)
dr = min(doit1(cx[i], cy[i], ux[j], uy[j]), doit1(ux[j], uy[j], 50, 0));
g[i] = exp((log(cs * dr / (dr + 1))) * log(doit1(cx[i], cy[i], 50, 0)));
}
for (int i = 1; i <= n; ++i) f[i][i] = 1;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
for (int k = 1; k <= n; ++k)
if ((f[i][k] * f[k][j] > f[i][j]) && (i != j) && (j != k) && (k != j))
f[i][j] = f[i][k] * f[k][j];
for (int i = 1; i <= n; ++i)
if (f[1][i] * g[i] > maxx)
maxx = f[1][i] * g[i];
printf("%.6lf\n", maxx);
return 0;
}