V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pipelining
V2EX  ›  算法

各位大哥,帮帮小弟吧,被一个算法难住了!

  •  1
     
  •   pipelining · 2023-03-10 16:52:10 +08:00 · 1388 次点击
    这是一个创建于 625 天前的主题,其中的信息可能已经有所发展或是发生改变。
    各位大哥,帮帮小弟吧,有一个算法搞不定。能否给小弟一些思路。
    场景如下
    > 有一组项目,每个项目都有起始年份和结束年份,同时每年需要花费一定已知金额的钱,而每年的总花费有一定限制,每年每个项目花费金额之和要在一个已知最大值最小值之内,每年的范围是不同的,我们可以调整项目的起始年份,使得每年每个项目花费金额之和满足在区间之内。算法要返回多组满足条件的项目起始年份集合
    9 条回复    2023-03-12 15:29:19 +08:00
    LeegoYih
        1
    LeegoYih  
       2023-03-10 16:53:26 +08:00   ❤️ 1
    试试 ChatGPT
    08110920
        2
    08110920  
       2023-03-10 16:55:29 +08:00
    1.将所有项目按照起始年份从小到大排序;

    2.初始化当前年份为第一个项目的起始年份,然后遍历所有项目,将每个项目的起始年份与当前年份进行比较:

    若当前年份在项目的时间范围内,则将该项目添加至当前年份的项目集合中;
    若当前年份超出项目时间范围,则将当前年份后移至下一个项目的起始年份,并清空当前年份的项目集合,再进行步骤 2 。
    3.对于每个年份的项目集合,计算其花费总和并判断是否满足每年的总花费限制;

    4.如果满足限制,则将该年份作为起始年份加入结果集合中。

    5.重复步骤 2-4 直到遍历完所有项目。

    需要注意的是,这个算法并不是一定能够保证找到所有满足条件的起始年份集合,因为有些项目可能无法被安排在规定的时间范围内。因此,这个算法可能只能找到一个近似解。
    pipelining
        3
    pipelining  
    OP
       2023-03-10 17:05:03 +08:00
    忘记说了,约束是每个项目可调整的范围是相同的,可调整年份为开始年份范围是所提供的项目之中的最小年份和这个最小年份加 5 这个区间之内。
    hhhhhh123
        4
    hhhhhh123  
       2023-03-10 17:14:39 +08:00
    我看不懂题目, 但是我看的懂例子, 可惜你没有
    pipelining
        5
    pipelining  
    OP
       2023-03-10 17:18:47 +08:00
    示例如下:projects = [
    {"start_year": 2000, "end_year": 2002, "costs": [100, 200, 300]},
    {"start_year": 2001, "end_year": 2003, "costs": [150, 250, 350]},
    {"start_year": 2002, "end_year": 2004, "costs": [200, 300, 400]},
    {"start_year": 2003, "end_year": 2005, "costs": [250, 350, 450]},
    {"start_year": 2002, "end_year": 2003, "costs": [300, 400, 500]},
    ]

    min_limits = [600, 800, 1000, 800, 600]
    max_limits = [700, 900, 1100, 900, 700]
    pipelining
        6
    pipelining  
    OP
       2023-03-10 17:19:40 +08:00
    可调整的项目开始年份可计算出来在 2000-2004 之间
    sexoutsex2011
        7
    sexoutsex2011  
       2023-03-10 17:21:15 +08:00
    chatGPT 的回答:

    这个问题可以使用贪心算法解决。

    步骤如下:

    根据每个项目的起始年份和结束年份,以及每年的总花费限制,将所有项目按照起始年份从小到大进行排序。

    遍历项目列表,并在每年的总花费限制范围内贪心地选择项目。

    对于每个年份,记录已选择项目中最早的起始年份。如果当前年份减去最早起始年份大于项目的持续年限,则将最早起始年份往后移动,直到满足条件。

    将满足条件的项目加入结果集合,继续遍历剩余项目,直到所有项目都被考虑过。

    返回多组满足条件的项目起始年份集合。

    具体实现可以使用一个哈希表来记录每个年份已选择的项目和它们的花费总和,以及一个堆来保存还未被考虑的项目。

    时间复杂度为 $O(n\log n)$ ,其中 $n$ 是项目的数量。
    chaoxu
        8
    chaoxu  
       2023-03-12 12:26:46 +08:00
    理解方式:

    输入整数函数$f_1,...,f_k$, 一些数字$l_1,...,l_m$,和$u_1,...,u_m$。
    你要找到$s_1,...,s_k$. 使得对于所有的$j$, $l_j \leq \sum_{i=1}^k f_i(j-s_i) \leq u_j$.

    可以复制粘贴到 mathb.in 看看
    chaoxu
        9
    chaoxu  
       2023-03-12 15:29:19 +08:00
    很显然问题是 NP-hard 的. 可以把 partition 问题规约(所有项目正好 1 年, 然后有 2 年可以用, 每年花费是所有项目的钱 /2)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4826 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 01:16 · PVG 09:16 · LAX 17:16 · JFK 20:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.