1 solutions
-
0
仔细读题,分析长颈鹿购买的流程,不难发现:只要第一次购买的饮料型号确定了下来,后面所有的购买流程以及会购买的饮料型号全都会确定下来。因为从第二次开始,所有的窗口都至多有一种有存货的饮料。
所以我们只需要从 进行枚举,每次分别枚举其出货正确或者出货错误时的购买流程,就可以计算其在这种情况下支出的费用。
每次具体模拟如下:首先支付对应费用,然后判断当前买到了哪个款式,对应款式设置为缺货状态,然后长颈鹿跳转到下一个窗口。每次在支付费用之后先判断,如果该窗口提供的两种饮料都缺货,则直接中断;反之,判断哪一种有存货,购买到对应的饮料种类,然后到对应的窗口。直至购买到的饮料是目标饮料为止。
最终结果的计算只要会数学期望的基础即可。把上面的每一种情况乘以该窗口第一次出货正确或者错误的概率。所有项加和之后除以 即为所求。
最后注意一下输出答案,不能和标准答案超过 ,所以要输出小数点后 位及以上。且为了精度问题,必须使用
double
或者long double
类型,实测float
的精度无法支持这样的运算。本题并没有想象中的那么签到,不过大家也要稳住心态,只要细心读题,慢慢构造模拟流程即可。
#include <stdio.h> #include <string.h> #define N 2010 int n, x; int a[N], b[N]; double p[N]; double ans; char remain[N]; // 剩余哪些有存货的饮料 // 模拟 st : 起始所在窗口 st_right : 是否出货正确的饮料 int simulation(int st, char st_right) { memset(remain, 1, n + 1); // 初始将所有饮料设置为有存货 int ret = a[st], buy = st_right ? st : b[st]; // 起始需要花钱 remain[buy] = 0; while (buy ^ x) { st = buy; ret += a[st]; // 先花钱,再判断是否有警报 if (!remain[st] && !remain[b[st]]) break; buy = remain[st] ? st : b[st]; remain[buy] = 0; } return ret; } int main() { scanf("%d%d", &n, &x); for (int i = 1; i <= n; ++i) scanf("%d%d%lf", &a[i], &b[i], &p[i]); for (int i = 1; i <= n; ++i) ans += simulation(i, 1) * p[i] + simulation(i, 0) * (1 - p[i]); // 由于和答案误差不超过 10^-6 就算正确,只要输出 6 位即以上小数即可。必须使用 `double` 或者 `long double` printf("%.7f", ans / n); // 数学期望,不要忘记除以 n }
- 1
Information
- ID
- 12
- Time
- 1000ms
- Memory
- 512MiB
- Difficulty
- 1
- Tags
- # Submissions
- 5
- Accepted
- 1
- Uploaded By