【问题标题】:How is this DP solution approached?这个 DP 解决方案是如何实现的?
【发布时间】:2012-04-28 04:47:27
【问题描述】:

一段时间以来,我一直在尝试解决这个 TopCoder 问题,但我无法提出基于 DP 的解决方案来解决这个问题(如下所示)。我也找到了其他人解决问题的方法(下面也给出了),但我什至无法理解。

谁能帮我解决这里的问题?我不明白什么思路会导致这个解决方案?如何在我的脑海中建立递归关系?我完全不知道如何解决这个问题,或者编写该解决方案的人是如何编写它的。

PS:我知道 TopCoder 有问题的社论,但这个还没有发布。我不知道为什么。

这是problem

Fox Ciel 有很多功课要做。作业包括一些 相互独立的任务。不同的任务可能需要不同的金额 的时间来完成。您将获得一个 int[] workCost。对于每个 i, 第 i 个任务需要 workCost[i] 秒才能完成。她愿意 参加一个聚会并见她的朋友,因此她想完成所有 尽快完成任务。

主要问题是所有的狐狸,包括夏尔,真的很讨厌做 在家工作。每只狐狸只愿意做其中一项任务。幸运的是, 哆啦A梦,22世纪的机器猫,与Fox Ciel分道扬镳 锤子:可以将任何一只狐狸一分为二的魔法道具。

给你一个 int splitCost。在狐狸身上使用劈锤是 瞬间。一旦锤子用在狐狸身上,狐狸就会开始 分裂。 splitCost 秒后她会变成两只狐狸—— 原来的狐狸和另一只全新的狐狸。当狐狸分裂时, 不允许再对她使用锤子。

一项任务的工作不能被打断:一旦狐狸开始工作 一项任务,她必须完成。不允许多只狐狸 合作完成同一任务。狐狸不能在她做任务的时候工作 用锤子劈开。可以分裂同一个狐狸 多次。之前和之后都可以分裂狐狸 她解决了其中一项任务。

计算并返回狐狸可以用的最短时间 解决所有任务。

这是solution

1:    
2:  const int maxN = 55;  
3:  int dp[maxN][maxN*2];  
4:  int N;  
5:  int splitC;  
6:  vector<int> workC;  
7:    
8:  int rec(int,int);  
9:  int FoxAndDoraemon::minTime(vector <int> workCost, int splitCost) {  
10:      
11:    sort(workCost.begin(), workCost.end());  
12:    N = workCost.size();  
13:    splitC = splitCost;  
14:    workC = workCost;  
15:       memset(dp, -1, sizeof(dp));  
16:      
17:    return rec(N-1, 1);  
18:  }  
19:    
20:  int rec(int jobs, int fox)  
21:  {  
22:    if(jobs == -1) return 0;  
23:      
24:    int& val = dp[jobs][fox];  
25:    if(val != -1) return val;  
26:    val = 0;  
27:      
28:    if( (jobs+1) <= fox) val = max(workC[jobs] , rec(jobs-1, fox-1));  
29:    else  
30:    {  
31:      //split fox  
32:      val = splitC + rec(jobs, fox + 1);  
33:        
34:      if( !(fox == 1 && jobs > 0) )  
35:        val = min(val, max(workC[jobs], rec(jobs-1, fox-1)));  
36:    }  
37:    return val;  
38:  }  
39:    

【问题讨论】:

    标签: c++ algorithm dynamic-programming


    【解决方案1】:

    DP 问题通常需要你做几个例子,而要擅长它的唯一方法就是练习。尝试解决 DP 中的一些标准问题类型,如最长递增子序列、背包、硬币变化、矩阵乘法、TSP 等。尝试这些类型的变体。

    关于上面的问题,有几点需要注意:

    • 您需要 N 只狐狸来完成 N 项任务(1 只狐狸只能完成 1 项任务)。因此,如果您已经克隆了 N 只狐狸,则无需再创建。而且,如果您有多个任务,则必须拆分第一只狐狸。
    • 每只狐狸可以做两件事
      • 将其拆分,然后计算所用的最短时间
      • 不要拆分,而是执行当前任务并计算用少一只狐狸执行剩余任务所需的时间。
        • 请注意,如果您有超过 1 只狐狸(或 1 只狐狸有 1 个任务),您只能选择不拆分。

    这应该可以让您对问题有所了解。我还没有彻底分析问题,但递归似乎并没有创建重叠调用,即如果我有 3 个任务和 2 个狐狸,我只调用该状态一次,不再调用。因此,该解决方案是常规递归解决方案,而不是 DP。

    【讨论】:

    • "如果你有多个任务,你必须拆分第一个狐狸。"不对。你可以让一只狐狸按顺序完成它们。但是,这可能不是最理想的。
    【解决方案2】:

    该社论现已在 TopCoder 网站上发布。您可以在那里看看!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多