zoukankan      html  css  js  c++  java
  • bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】

    传送门: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 <cstdio>
    #include <cstring>
    
    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
    ", dp(ini_neko, ini_mouse));
    	return 0;
    }
    

      

  • 相关阅读:
    Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup
    ValidForm.js的使用注意点
    我的第一个敏捷项目总结
    七月在线机器学习项目
    吴恩达机器学习
    emoji情感分类器
    序列模型实践工程
    序列模型-NLP和词嵌入
    吴恩达深度学习
    序列模型
  • 原文地址:https://www.cnblogs.com/ciao-sora/p/6111241.html
Copyright © 2011-2022 走看看