轻识Logo
目录

    教你用 Python 动态规划:特朗普怎样才能赢?

    美国大选正在如火如荼进行当中,假如你是特朗普的竞选助手,大选前要去各州开展竞选宣传活动,但是现在你只有10天时间,没有办法每个州都去,需要根据各州的重要性和时间花费拿出一套方案,否则就将被特朗普fire掉

    假设每个州初始情况都是中立的,只要去开展宣传活动就能获得选票,每个州的选举人票数是不一样的,但是票数越多的州需要花费的时间也越多,在时间有限的情况下,你该怎么安排行程,让竞选的胜算更大呢?

    下面是每个州的选举人票数:

    为了把问题简化,我们这里只考虑取选票数前10的州,time字段表示去这个州宣传活动所需的时间,单位是天:

    all_states = [
        {'name':'加利福尼亚州''votes':55'time':5},
        {'name':'德克萨斯州''votes':38'time':3},
        {'name':'佛罗里达州''votes':29,'time':2},
        {'name':'纽约州''votes':29'time':2},
        {'name':'伊利诺伊州''votes':20'time':1},
        {'name':'宾西法利亚州''votes':20,'time':1},
        {'name':'俄亥俄州','votes':18,'time':1},
        {'name':'密歇根州','votes':16,'time':1},
        {'name':'乔治亚州''votes':16,'time':1},
        {'name':'北卡罗来纳州''votes':15,'time':1}
    ]

    递归求解

    第一种办法,递归求解。

    对于每一个州,你有两种选择:去或者不去。

    如果去,则获得的选票是:这个州的选票 + 剩下时间里去剩下州能获得的最多票数

    如果不去,则获得的选票是:剩下时间(这一次不去就没花时间)里去剩下州能获得的最多票数

    最后,比较去或者不去的结果,选择更优的方案。

    这里,把剩下时间里去剩下州能获得的最多票数定义为一个函数,随着上面问题的拆解,不断递归:

    # 递归解决
    # 在指定索引后的州中,剩余时间内,能获得的最多选票
    def recurse_solution(states, index, time):

        if len(states) == 0 or index >= len(states) or time <= 0:
            return 0

        # 去这个州(时间还够的话)
        a = 0
        if states[index]['time'] <= time:
            a = states[index]['votes'] + recurse_solution(states, index + 1, time-states[index]['time'])

        # 不去这个州
        b = recurse_solution(states, index + 1, time)

        return max(a, b)

    def main():
        print("max votes: %d" % recurse_solution(all_states, 010))

    记忆化搜索

    上面的递归过程,如同一个二叉树,从根节点不断分叉成:去 / 不去 两个分支,直到叶子节点(剩下州或剩下时间为0)。

    然后选出各个路径中和最大的那一条。

    递归求解会有很多重叠子问题,就如同那个二叉树中会有很多重叠的子树,重复计算浪费很多时间。

    新的方案中引入一个记忆存储memo,定义为指定索引后的州中,剩余时间内,能获得的最多选票,每次计算完后将其记录在案,后续遇到直接查表,不再重复计算:

    # 引入记忆化搜索
    # memo[index][time]: 在指定索引后的州中,剩余时间内,能获得的最多选票
    memo = [[0 for i in range(100)] for j in range(100)]
    def memo_search_solution(states, index, time):

        if len(states) == 0 or index >= len(states) or time <= 0:
            return 0

        # 如果记忆表中存有历史结果,直接使用
        if memo[index][time] != 0:
            return memo[index][time]

        # 去这个州(时间还够的话)
        a = 0
        if states[index]['time'] <= time:
            a = states[index]['votes'] + memo_search_solution(states, index + 1, time-states[index]['time'])

        # 不去这个州
        b = memo_search_solution(states, index + 1, time)

        # 记录这次结果,供下次使用
        memo[index][time] = max(a, b)

        return max(a, b)

    def main():
        print("max votes: %d" % memo_search_solution(all_states, 010))

    动态规划

    上面的递归和引入记忆化搜索后的递归,都是自顶向下的思考这个问题:在去与不去两种方案中选择。接着再继续在子问题中再次思考去与不去。

    而动态规划则调转枪头,自下而上

    先解决只有1个州,只有1天时间,能获得的最大选票

    再解决有2个州,只有1天时间,能获得的最大选票

    ···

    再解决全部州,只有1天时间,能获得的最大选票

    再解决全部州,有2天时间,能获得的最大选票

    ···

    最后解决全部州,有10天时间,能获得的最大选票

    如同正在进行的人口普查,下面每个街道的数据知道了,想知道这个区县的数据就容易了。

    知道了每个区县的数据,想知道这个市的数据就容易了。

    知道了每个市的数据,想知道这个省的就容易了。

    以此类推。

    ## 动态规划解决
    def dp_solution(states, time):

        # memo[index][time]: 在指定索引后的州中,剩余时间内,能获得的最多选票
        memo = [[0 for i in range(time+1)] for j in range(len(states)+1)]

        for i in range(1, len(states) + 1):
            for j in range(1, time+1):
                if states[i - 1]['time'] <= j:
                    # 如果时间还够

                    # 选择不去
                    a = memo[i-1][j]

                    # 选择去
                    b = memo[i-1][j-states[i-1]['time']] + states[i-1]['votes']

                    # 记录去和不去两种选择的最优值
                    memo[i][j] = max(a, b)
                else:
                    # 如果时间不够
                    memo[i][j] = memo[i-1][j]

        return memo[len(states)][time]
        
    def main():
        print("max votes: %d" % dp_solution(all_states, 10))

    执行上面的代码输出:

    max votes: 157

    通过上面的代码能够知道特朗普能够获得的最多选票数:157张。

    你高高兴兴的告诉特朗普:“Hi,Trump,这10天的宣传活动,你最多能获得157张选票”

    但是现在特朗普问你:“去哪些州?行程怎么安排”

    你支支吾吾半天没答出来。

    特朗普见状说到:“还是让我亲自来,没有人比我更懂动态规划”


    往期文章

    最全总结 | 聊聊 Python 办公自动化之 Excel(上)

    最全总结 | 聊聊 Python 办公自动化之 Excel(中)

    最全总结 | 聊聊 Python 办公自动化之 Excel(下)

    浏览 15
    点赞
    评论
    收藏
    分享

    手机扫一扫分享

    举报
    麦西尔
    本店特色美食。黑芝麻,草莓甜心,苦咖啡,蓝莓派,西瓜蛋糕,草莓饼,紫色小鱼,鸡蛋芝麻酥饼,蛋挞,草莓姐,彩虹蛋糕,蛋黄酥
    麦西尔
    0
    西麦烘焙
    本店特色美食。双层祝寿蛋糕,鲜花蛋糕,芭比娃娃款,动物鲜奶蛋糕,水果N款,helloKitty蛋糕K款,熊出没蛋糕E款,冰激凌裸蛋糕D款,新西兰动物奶油,小猪佩琪冰激凌
    西麦烘焙
    0
    西麦CIMI
    中山市西麦电器有限公司成立于2014-07-10,注册地位于西藏昌都市丁青县东升镇民济路19号A室,法定代表人为唐召利,经营范围包括销售:家用电器、电子产品、五金制品、塑料制品、日用品、厨房用品。(依
    西麦CIMI
    0
    麦肯西
    麦肯西
    0
    西麦CIMI
    中山市西麦电器有限公司成立于2014-07-10,注册地位于西藏 昌都市 丁青县 东升镇民济路19号
    西麦CIMI
    0
    西麦VCMY
    广州西麦科技股份有限公司于2003年成立,于2015年11月18日成功挂牌新三板,证券代码为8342
    西麦VCMY
    0
    西麦科技
    西麦科技
    0
    西麦检测
    深圳市西麦检测技术有限公司主要为消费类电子产品、汽车类电子产品的制造和检验提供最好的设备(包含射频-微波测试设备、电磁兼容测试设备、电子产品通用测试设备等设备)、技术以及测试系统集成方案。
    西麦检测
    0
    西麦燕麦片
    西麦燕麦片
    0
    点赞
    评论
    收藏
    分享

    手机扫一扫分享

    举报

    深圳SEO优化公司锦州百搜标王公司铜仁百度关键词包年推广公司许昌网站优化排名公司坂田网站推广推荐咸宁建站滁州网站优化按天收费公司淮南网站优化公司济源建站公司西宁建站报价木棉湾模板网站建设价格黄冈网页设计平顶山优化价格辽阳网页设计公司阜阳企业网站建设价格丹竹头建站公司龙华网页设计哪家好济南高端网站设计多少钱海西网站定制价格海南网站推广系统临沧建设网站公司南平SEO按天扣费公司长沙关键词按天扣费推荐邵阳网站改版报价包头网站改版推荐湘潭网站排名优化扬州网站开发陇南网站建设设计价格汉中网页设计推荐朝阳关键词按天计费公司商洛网络推广公司歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

    深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化