TopCoder上的生物训练动态编程

时间:2013-06-25 10:08:38

标签: algorithm dynamic-programming

我一直在尝试解决the following TopCoder problem

  

你正在玩一个策略游戏,你希望训练最强大的军队进行最后的战斗。游戏中有N级生物,编号从0到N-1(包括0和N-1)。你已经在你的军队中有一些生物和D天来训练他们。你拥有的生物数量以int []计数给出。它包含N个元素,其第i个元素是级别i的生物数量。

     

在每一天,你可以选择一个生物并进行训练。训练将生物的等级提高1,即等级0的生物变为等级1的生物,等级1的生物变为等级2的生物,依此类推。唯一的例外是N-1级别的生物 - 这样的生物无法训练,因为N-1是最大可能的等级。您可以在一天以上的时间内训练同一个生物。例如,如果你在3天内训练一个生物,它将获得3个等级。在那些日子里,你也可以跳过几天而不训练任何生物。

     

你被赋予一个int []的力量,其中第i个力量元素是一个等级为i的生物的力量。你的军队的力量是其所有生物的力量的总和。在所有D天的训练结束后,返回你的军队可以拥有的最大可能力量。

我无法获得算法。这是一个动态编程问题,我无法找到任何合适的子问题来解决它。

任何人都可以向我提供解决问题需要考虑的子问题吗?

我也想知道你到达解决方案的思维过程。

2 个答案:

答案 0 :(得分:1)

Topcoder包括为他们的问题提供解决方案的社论。

解决方法是here

  

我们可以完全自由地进行升级。在寻找时   最优算法,自由是坏的 - 它给了我们太多   尝试的可能性。我们如何限制搜索?

     

我们可以决定在进行升级时有点系统化。我们会   首先花一些(可能是零)天升级0级   生物,然后我们将升级一些1级生物,依此类推。   显然,通过这种方式,我们将能够实现最佳的总功率。   (如果我们有一个最佳解决方案,可以在其他方面进行升级   顺序,我们可以轻松地重新排列它们并按照我们的顺序进行。)

     

现在我们可以轻松编写一个可以尝试所有的递归解决方案   可能性。当然,我们想要记住计算值   避免指数时间复杂性。为此,我们需要确定   正是用于描述计算状态的内容。

     

两个参数是显而易见的:我们生物的等级L.   目前正在升级,剩下的D天数。但是,这是   不是全部,还有一个更重要的问题。我们可能已经做了一些   之前的升级,以及当前L级生物的数量   可能高于输入值。这个差异将是第三个,   最后,参数。

     

最多N = 50级,最多D = 100天。显然,   第三个参数永远不能超过D.因此最多   N * D * D = 500,000个州。计算一个状态的时间复杂度是   O(D),导致总时间复杂度O(N * D ^ 3)。

  long long memo[52][102][102];
  long long counts[52], powers[52];
  int N;

  long long solve(int level, int add, long long upgrades) {
    long long &res = memo[level][add][upgrades];
    if (res >= 0) return res;
    res = 0;
    if (level==N) return res;
    int maxUpgrades = min( upgrades, counts[level]+add );
    for (int now=0; now<=maxUpgrades; now++) {
      long long thisLevel = powers[level] * (counts[level]+add-now);
      long long nextLevels = solve(level+1,now,upgrades-now);
      res = max( res, thisLevel+nextLevels );
    }
    return res;
  }

  long long maximumPower(vector <int> _count, vector <int> _power, int D) {
    memset(memo,-1,sizeof(memo));
    N = _count.size();
    for (int i=0; i<N; i++) counts[i] = _count[i];
    for (int i=0; i<N; i++) powers[i] = _power[i];
    return solve(0,0,D);
  }

答案 1 :(得分:0)

它看起来像一个dp,很有意思我想尝试一下..我会以这种方式接近它:

我创建了一个级别之间的权力差异数组,然后追求升级低于该级别的生物,以获得我可以添加的最大功率。我认为这可能是一个贪婪或背包,升级的是关键决定。

编辑:好吧,我忘了提到你应该对这个数组做什么:你应该对它进行排序以获得排序的索引..它实际上比数组更像是一个数据,因为你想要在进程中混洗索引排序,以便你可以知道哪个级别是最高的差异,正面或负面等等。