zoukankan      html  css  js  c++  java
  • 给你出道题---最佳组合问题

    给定N组数字,每组数字组内数字之间互不相同,组间数字可能相同。这些数字都是正整数,现在从这N组数字中选择尽量多的数字,使得选出来的数字满足以下条件:

    • 每组只选出一个数字
    • 选出来的数字互不相同

    要求:使选出来的数字之和尽量大。

    暴力想法显而易见,但是有没有更完美的方法呢?

    import numpy as np
    
    
    def generate_problem():
        group_count = np.random.randint(5, 6)
        groups = []
        for i in range(group_count):
            group_size = np.random.randint(2, 5)
            groups.append(sorted(list(set(np.random.randint(1, 10, group_size))), reverse=True))
        return groups
    
    
    def brute_force(groups):
        groups = [i for i in groups if i]
        if not groups:
            return 0
        max_value = max(i[0] for i in groups)
        big_groups = [i for i in groups if i[0] == max_value]
        ans = 0
        for big in big_groups:
            next_groups = [j[1:] if j[0] == max_value else j for j in groups if j != big]
            s = brute_force(next_groups) + max_value
            ans = max(ans, s)
        return ans
    
    
    def main():
        for i in range(100):
            p = generate_problem()
            s = brute_force(p)
            print(p)
            print(s)
            print('=' * 10)
    
    
    main()
    
    

    这个问题等价于:
    将全部数字合并,去重,排序得到一个数组A,下面构建一个矩阵,数组A为列名,数组每行为每组的数字,如果存在则用此值代替,如果不存在,用0代替。这样就得到一个稀疏矩阵。
    此题转化为:在这个矩阵中寻找最优组合,要求每行、每列只能选择一个数字,选定若干数字使最终结果之和最大。

    此问题其实是二分图。
    将全部数字合并,去重之后放在右面,将全部数组放在左边。如果左边的数组X包含右边的数字Y,则在它们之间连一条线。左边的结点和右边的结点都只能使用一次,求最大匹配(边权之和最大)。

    在本题中,最终的二分图模型左右结点个数可能不等,所以无法找到完美匹配。

    留一道更难的题:
    给定一个$N imes M$的矩阵,每行每列最多只能选择一个元素,最终选出来的元素不可重复,要使选出来的数字之和尽量大。

  • 相关阅读:
    JUC学习笔记--从阿里Java开发手册学习线程池的正确创建方法
    1.初识Python
    学会 Debug
    如何找出nginx配置文件的所在位置?
    一个技术人,如何做到比别人更突出
    生产环境如何快速跟踪、分析、定位问题-Java
    如何优化代码中大量的if/else,switch/case?
    UML类图几种关系的总结
    DateUtils常用方法
    如何存储和表示数字—二进制(一)
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/10539712.html
Copyright © 2011-2022 走看看