zoukankan      html  css  js  c++  java
  • 找钥匙问题

    https://www.zhihu.com/question/307814660/answer/566825886

    小明把钥匙丢了,只知道钥匙肯定丢在家里或者学校里。如果丢在了家里,在家里找一次能够找到的概率为a;如果丢在了学校里,在学校里找一次能够找到的概率为b。最初小明认为钥匙丢在家里的概率为p。问:小明应该采取什么策略来找钥匙才能够最快找到钥匙(寻找次数尽量少)?期望寻找次数是多少?

    假如第一次在家里找,结果没有找到,钥匙依旧在家的概率为$p_1=frac{p imes(1-a)}{1-p imes a}$
    如果第一次在学校找,结果没找到,钥匙依旧在家的概率为$p_1=frac{p}{1-(1-p) imes b}$

    $$f(p)=min{cost_{home},cost_{school}}$$
    $$cost_{home}=canfind imes1+(1-canfind) imes [1+f(p_1)]$$
    $$cost_{school}=canfind imes1+(1-canfind) imes [1+f(p_1)]$$

    其中canfind表示能够找到的概率, $p_1$ 表示经过一次寻找之后钥匙在家的概率。如果在家里找到了,那么只需要一步就能找到钥匙;如果没有找到,那么需要 $1+f(p_1)$步才能找到钥匙。

    贪心法应该是对的
    根据 $p imes a>(1-p) imes b $来决定去家里找还是学校找。
    假如寻找次数为16步,那么所有的寻找序列构成一个深度为16的二叉树。从根节点到叶子节点的路径就表示一个决策。每个结点都有一个数字f(node)表示该结点的找到钥匙的期望寻找次数。当前节点的期望寻找次数依赖于它的两个儿子(分别对应去家里找和去学校找的期望寻找次数)中的期望寻找次数较小者。按照这个方法,暴力枚举整个满二叉树上的决策,发现最终得到的决策路径和贪心法找大的决策路径是一致的。

    期望寻找次数为:3.1857095316916766

    f(p) 函数表示钥匙在家时,期望寻找次数。这个函数表达式为
    $$f(p)=min{1+(1-pa)f(frac{p-pa} { 1 - pa}),1+(1-b+pb)f(frac{p}{1-b+pb})}$$

    根据贪心法(若不是此问题的具体情境,很难看出上式可以转化为条件函数)可以化简此式:
    贪心条件为 $pacirc(1-p)b$,也就是 $pcirc frac{b}{a+b}$
    这个公式等价于

    $$f(p)= egin{cases} 1+(1-pa)f(frac{p-pa} { 1 - pa}) when pgtfrac{b}{a+b} \ 1+(1-b+pb)f(frac{p}{1-b+pb}) when plefrac{b}{a+b}\ end{cases} $$

    其中,a、b为常量,p取值范围(0,1)
    这个解析式是否能够进一步化简呢?

    a = 0.8  # 在家找到的概率
    b = 0.4  # 在学校找到的概率
    
    
    def solve(p, c):
        # 钥匙在家的概率为p,返回最优决策、期望找到钥匙所花费的步数
        if c == 0:
            return max(1 / a, 1 / b)  # 如果最后没有找到
        if p > b / (a + b):
            step = solve(p * (1 - a) / (1 - p * a), c - 1)
            ifhome = 1 + step * (1 - p * a)  # 如果去家里找,期望找到的步数
            return ifhome
        else:
            step = solve(p / (1 - (1 - p) * b), c - 1)
            ifschool = 1 + step * (1 - (1 - p) * b)
            # 选取两个儿子中期望步数较小者
            return ifschool
    
    
    import pylab as plt
    import numpy as np
    print(solve(0.3, 200))
    xs = np.linspace(0, 1, 1000)
    ps = [solve(i, 200) for i in xs]
    plt.plot(xs, ps)
    plt.xlabel("p")
    plt.ylabel("step")
    print(b/(a+b))
    plt.plot([b/(a+b)] * 100, np.linspace(0, max(ps), 100), c='r')
    plt.show()
    
    

    使用tensorflow求解迭代形式的函数方程

    import tensorflow as tf
    import pylab as plt
    import numpy as np
    import os
    a = 0.8
    b = 0.4
    c = 1000
    
    loss = tf.constant(0.0)
    xs = np.linspace(0, 1, c)
    fp = tf.Variable(tf.random_uniform((c,)), dtype=tf.float32)
    if not os.path.exists("img"):
        os.mkdir('img')
    for i in range(c):
        p = xs[i]
        if p > b / (a + b):
            next_p = (p - p * a) / (1 - p * a)
            next_ind = int(round(next_p * c))
            next_ind = min(c - 1, next_ind)
            y = 1 + (1 - p * a) * fp[next_ind]
        else:
            next_p = p / (1 - b + p * a)
            next_ind = int(round(next_p * c))
            next_ind = min(c - 1, next_ind)
            y = 1 + (1 - b + p * b) * fp[next_ind]
        loss = loss + tf.abs(y - fp[i])
    train_op = tf.train.AdamOptimizer(0.01).minimize(loss)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for i in range(100000):
            _, lo = sess.run([train_op, loss])
            if i % 1000 == 0:
                if i % 5000 == 0:
                    plt.close()
                    plt.figure()
                print(i, lo)
                plt.plot(xs, sess.run(fp))
                plt.savefig("img/%s.jpg" % i)
    
    
  • 相关阅读:
    神经网络和深度学习之——前馈神经网络
    神经网络和深度学习之感知器工作原理
    神经网络和深度学习之神经元和感知器
    基于keras的BiLstm与CRF实现命名实体标注
    基于双向BiLstm神经网络的中文分词详解及源码
    Net Core中数据库事务隔离详解——以Dapper和Mysql为例
    利用卷积神经网络(VGG19)实现火灾分类(附tensorflow代码及训练集)
    AlexNet 网络详解及Tensorflow实现源码
    ASP.NET Core MVC I/O编程模型
    Tensorflow开发环境配置及其基本概念
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/10227020.html
Copyright © 2011-2022 走看看