博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】
阅读量:4604 次
发布时间:2019-06-09

本文共 2226 字,大约阅读时间需要 7 分钟。

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1415

noip2016 D1T3,多么痛的领悟。。。看来要恶补一下与期望相关的东西了。

这是一道经典的求期望的题,尽管我的代码里把那个记忆化搜索那个叫做dp,但事实上这不是动态规划,只是递推。

先预处理出x[i][j],表示聪聪在i,可可在j时,下一步聪聪到达的顶点标号,f[i][j]是那张记忆化搜索的表,表示聪聪在i,可可在j时,期望所需的时间,out[i]表示i点的出度(其实就是度啦,无向图没什么入度出度的)。显然,下一个单位时间聪聪的位置是x[x[i][j]][j],而可可是在所有与j相邻的节点或者j自己中随机挑一个到达,每个的概率都是1 / (out[j] + 1),所以有

f[i][j] = ( sigma(  f[x[x[i][j]][j]][k]  ) + f[x[x[i][j]][j]][j] ) / (out[j] + 1) + 1,其中k表示每个与j相邻的节点。

然后写一个记忆化搜索就完事咯~

#include 
#include
const int maxn = 1005, maxe = 1005;int n, e, ini_neko, ini_mouse, t1, t2;int head[maxn], to[maxe << 1], next[maxe << 1], lb, out[maxn];int que[maxn], head_, tail, h, x[maxn][maxn], d[maxn][maxn];double f[maxn][maxn];inline void ist(int aa, int ss) { to[lb] = ss; next[lb] = head[aa]; head[aa] = lb; ++out[aa]; ++lb;}double dp(int i, int j) { if (f[i][j] != -1.0) { return f[i][j]; } if (i == j) { return f[i][j] = 0.0; } if (x[i][j] == j) { return f[i][j] = 1.0; } if (x[x[i][j]][j] == j) { return f[i][j] = 1.0; } f[i][j] = 0.0; for (int k = head[j]; k != -1; k = next[k]) { f[i][j] += dp(x[x[i][j]][j], to[k]); } f[i][j] = (f[i][j] + dp(x[x[i][j]][j], j)) / (double)(out[j] + 1) + 1; return f[i][j];}int main(void) { //freopen("in.txt", "r", stdin); memset(head, -1, sizeof head); memset(next, -1, sizeof next); for (int i = 0; i < maxn; ++i) { for (int j = 0; j < maxn; ++j) { f[i][j] = -1.0; } } scanf("%d%d", &n, &e); scanf("%d%d", &ini_neko, &ini_mouse); while (e--) { scanf("%d%d", &t1, &t2); ist(t1, t2); ist(t2, t1); } memset(d, -1, sizeof d); for (int i = 1; i <= n; ++i) { memset(que, 0, sizeof que); head_ = tail = 0; que[tail++] = i; d[i][i] = 0; while (head_ != tail) { h = que[head_++]; for (int j = head[h]; j != -1; j = next[j]) { if (d[i][to[j]] == -1) { d[i][to[j]] = d[i][h] + 1; que[tail++] = to[j]; } } } } memset(x, 0x3c, sizeof x); for (int i = 1; i <= n; ++i) { for (int k = head[i]; k != -1; k = next[k]) { for (int j = 1; j <= n; ++j) { if (d[i][j] == d[to[k]][j] + 1 && x[i][j] > to[k]) { x[i][j] = to[k]; } } } } printf("%.3f\n", dp(ini_neko, ini_mouse)); return 0;}

  

转载于:https://www.cnblogs.com/ciao-sora/p/6111241.html

你可能感兴趣的文章
为什么JavaScript里面0.1+0.2 === 0.3是false
查看>>
docker swarm集群搭建
查看>>
BZOJ 1303: [CQOI2009]中位数图 问题转化_扫描_思维
查看>>
SP1026 FAVDICE - Favorite Dice 数学期望
查看>>
NodeJS、NPM安装配置步骤(windows版本)
查看>>
【矩阵+十进制快速幂】[NOI2013]矩阵游戏
查看>>
Java一个简单的文件工具集
查看>>
蓝牙BLE扫描成功,log中打印出扫描到的设备
查看>>
一般处理应用页中绑定方法代码段
查看>>
无限鼠标没反应了
查看>>
CSU - 1356 Catch(dfs染色两种写法,和hdu4751比较)
查看>>
zabbix监控php-fpm的性能
查看>>
温故知新 div + css笔记
查看>>
针对降质模型中的模糊SR
查看>>
POJ1142Smith Numbers一道简单的数学题
查看>>
UIButton(改变Title和image位置)
查看>>
Linux-使用之vim编译安装出现的问题
查看>>
codevs 3314 魔法森林
查看>>
mac os x mysql 出现./mysql: unknown variable 'sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABL 问题...
查看>>
桐桐的贸易--WA
查看>>