zoukankan      html  css  js  c++  java
  • 算法——动态规划

    行和列的思想:

    from collections import namedtuple
    from pprint import pprint
    
    """
    动态规划算法
    旅行行程最大化:
        假设要去伦敦独家,假期是两天,但是想去的游览地点很多,你没发前往每一个地方游览,因此你需要列一个清单。
        对于想起的名声景点,都列出所需的时间和景点的推荐指数,设计算法,在指定的时间内将此次旅行规划到指数最大化
    背包问题:
        假设你是一个小偷,你的背包只能装4磅的物品,现有一个可偷清单,分别标有物品的重量和价值,设计算法实现偷窃的价值最大化
    野营问题:
        假设你要出克玩,你的背包容量为6磅,需要决定携带哪些物品,实现价值最大化
    
    附加:
        1. 有些算法并非精确地解决步骤,而只是帮助你理清思路的框架
    
        2. 相同的系数,最终保留的是偏后者的,就是清单里面靠后的,所以相同系数自己比较喜欢的,要写在后面
    """
    
    
    item = namedtuple('项目', ['name', 'requirement', 'coefficient'])
    
    def main(data, max_requirement):
        """
        data:计划清单
        max_requirement: 预计最大条件
        """
        # 统计列数
        requirements = [i.requirement for i in data]
        min_col = min(requirements)
        col_num = int(max_requirement // min_col)
        row_num = len(data)
        # 初始化数据结构
        graph = [[{'total': 0, 'item': []} for j in range(col_num)] for i in range(row_num)]
        # 列
        col_context = [min_col+min_col*i for i in range(col_num)]
    
    
        def get_col_index_item_without_self(row, rest_index, name):
            """从下往上(先出的结果就是最大的系数项),获取一个不包含自己的item"""
            item = {'total': 0, 'item': []}
            for r in range(row, -1, -1):
                if name not in graph[r][rest_index]['item']:
                    return graph[r][rest_index]
            return item
                
    
        # 开始动态规划
        for row in range(row_num):
            for col in range(col_num):
                name = data[row].name # 当前位置的条件值
                requirement = data[row].requirement # 当前位置的条件值
                coefficient = data[row].coefficient # 当前位置的系数值
                # 如果当前条件小于等于对应列
                if requirement <= col_context[col]:
                    # 假设用当前行内容条件填充,查看是否还有剩余
                    rest = col_context[col] - requirement
                    if rest:
                        # 有剩余的话
                        rest_index = col_context.index(rest)
                        # 查看剩余的对应列,当前行开始,行为阶梯,往上走
                        max_item = get_col_index_item_without_self(row, rest_index, name)
                        # 这就是当前内容+剩余的最大系数值,简称sum
                        maybe_max = coefficient + max_item['total']
                        # 将这个sum和row-1,col比较,高则合并,低则自己
                        same_col_top_row_item = graph[row and row-1 or 0][col]
                        if maybe_max >= same_col_top_row_item.get('total'):
                            graph[row][col] = {
                                'total': max_item['total'] + coefficient,
                                'item': max_item['item'] + [name]
                            }
                        elif maybe_max < same_col_top_row_item['total']:
                            graph[row][col] = same_col_top_row_item
                    else:
                        # 没有剩余
                        # 就看当前内容会不会比同列上一行的系数高,高则用,低则自己
                        top_row_item = graph[row and row-1 or 0][col]
                        if top_row_item['total'] > coefficient:  # 高则用
                            graph[row][col] = top_row_item
                        else:  # 低则自己
                            graph[row][col] = {'total': coefficient, 'item': [name]}
                else:  # 当前条件大于对应列
                    if row == 0:  # 第一行就直接赋空
                        graph[row][col] = {'total': 0, 'item': []}
                    # 不是第一行就取等列上一行的数据
                    else:
                        graph[row][col] = graph[row-1][col]
    
        return graph
    
    
    if __name__ == '__main__':
        # 旅行行程最大化
        check_list = [
            item('威斯敏斯特教堂', 0.5, 7),
            item('环球剧场', 0.5, 6),
            item('英国国家美术馆', 1, 9),
            item('大英博物馆', 2, 9),
            item('圣保罗大教堂', 0.5, 8),
        ]
        max_requirement = 2
        """
        [{'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂'], 'total': 7}]
    
        [{'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂', '环球剧场'], 'total': 13},
        {'item': ['威斯敏斯特教堂', '环球剧场'], 'total': 13},
        {'item': ['威斯敏斯特教堂', '环球剧场'], 'total': 13}]
    
        [{'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂', '环球剧场'], 'total': 13},
        {'item': ['威斯敏斯特教堂', '英国国家美术馆'], 'total': 16},
        {'item': ['威斯敏斯特教堂', '环球剧场', '英国国家美术馆'], 'total': 22}]
    
        [{'item': ['威斯敏斯特教堂'], 'total': 7},
        {'item': ['威斯敏斯特教堂', '环球剧场'], 'total': 13},
        {'item': ['威斯敏斯特教堂', '英国国家美术馆'], 'total': 16},
        {'item': ['威斯敏斯特教堂', '环球剧场', '英国国家美术馆'], 'total': 22}]
    
        [{'item': ['圣保罗大教堂'], 'total': 8},
        {'item': ['威斯敏斯特教堂', '圣保罗大教堂'], 'total': 15},
        {'item': ['威斯敏斯特教堂', '环球剧场', '圣保罗大教堂'], 'total': 21},
        {'item': ['威斯敏斯特教堂', '英国国家美术馆', '圣保罗大教堂'], 'total': 24}]
        """
    
        # 背包问题
        check_list = [
            item('音响', 4, 3000),
            item('笔记本电脑', 3, 2000),
            item('吉他', 1, 1500),
            item('iphone', 1, 2000)
        ]
        max_requirement = 4
        """
        [{'item': [], 'total': 0},
        {'item': [], 'total': 0},
        {'item': [], 'total': 0},
        {'item': ['音响'], 'total': 3000}]
    
        [{'item': [], 'total': 0},
        {'item': [], 'total': 0},
        {'item': ['笔记本电脑'], 'total': 2000},
        {'item': ['音响'], 'total': 3000}]
    
        [{'item': ['吉他'], 'total': 1500},
        {'item': ['吉他'], 'total': 1500},
        {'item': ['笔记本电脑'], 'total': 2000},
        {'item': ['笔记本电脑', '吉他'], 'total': 3500}]
    
        [{'item': ['iphone'], 'total': 2000},
        {'item': ['吉他', 'iphone'], 'total': 3500},
        {'item': ['吉他', 'iphone'], 'total': 3500},
        {'item': ['笔记本电脑', 'iphone'], 'total': 4000}]
        """
    
        # 野营问题
        check_list = [
            item('水', 3, 10),
            item('书', 1, 3),
            item('食物', 2, 9),
            item('夹克', 2, 5),
            item('相机', 1, 6),
        ]
        max_requirement = 6
        """
        [{'item': [], 'total': 0},
        {'item': [], 'total': 0},
        {'item': ['水'], 'total': 10},
        {'item': ['水'], 'total': 10},
        {'item': ['水'], 'total': 10},
        {'item': ['水'], 'total': 10}]
    
        [{'item': ['书'], 'total': 3},
        {'item': ['书'], 'total': 3},
        {'item': ['水'], 'total': 10},
        {'item': ['水', '书'], 'total': 13},
        {'item': ['水', '书'], 'total': 13},
        {'item': ['水', '书'], 'total': 13}]
    
        [{'item': ['书'], 'total': 3},
        {'item': ['食物'], 'total': 9},
        {'item': ['书', '食物'], 'total': 12},
        {'item': ['水', '书'], 'total': 13},
        {'item': ['水', '食物'], 'total': 19},
        {'item': ['水', '书', '食物'], 'total': 22}]
    
        [{'item': ['书'], 'total': 3},
        {'item': ['食物'], 'total': 9},
        {'item': ['书', '食物'], 'total': 12},
        {'item': ['食物', '夹克'], 'total': 14},
        {'item': ['水', '食物'], 'total': 19},
        {'item': ['水', '书', '食物'], 'total': 22}]
    
        [{'item': ['相机'], 'total': 6},
        {'item': ['书', '相机'], 'total': 9},
        {'item': ['食物', '相机'], 'total': 15},
        {'item': ['书', '食物', '相机'], 'total': 18},
        {'item': ['食物', '夹克', '相机'], 'total': 20},
        {'item': ['水', '食物', '相机'], 'total': 25}]
        """
    
    
        for i in main(check_list, max_requirement):
            pprint(i)
            print()
    
  • 相关阅读:
    python管理包(模块和包的应用)
    简单运行 Jupyter Notebook
    Linux出现“FirewallD is not running”解决办法
    Mindjet MindManager2020切换中文界面的教程
    idea 快捷键汇总
    南怀瑾经典语录
    CentOS 7 安装SonarQube 8.3版本
    Jenkins插件开发完全示例
    Jenkins在Pod中实现Docker in Docker并用kubectl进行部署
    Jenkins的kubernetes-plugin使用方法
  • 原文地址:https://www.cnblogs.com/pywjh/p/14945453.html
Copyright © 2011-2022 走看看