Algorithm 基于TopCoder的生物训练动态规划

Algorithm 基于TopCoder的生物训练动态规划,algorithm,dynamic-programming,Algorithm,Dynamic Programming,我一直在努力解决: 你正在玩一个战略游戏,你希望为最后的战斗训练最强大的军队。游戏中有N个级别的生物,编号从0到N-1不等。你的军队里已经有了一些生物,你需要花上几天的时间来训练它们。你拥有的生物数量以int[]计数给出。它包含N个元素,第i个元素是一级生物的数量 每天,你可以选择一种生物并训练它。训练使一个生物的等级提高1,即0级生物变为1级生物,1级生物变为2级生物,依此类推。唯一的例外是N-1级的生物-这类生物不能训练,因为N-1是最大的可能等级。你可以在一天以上的时间里训练同一个生物。例

我一直在努力解决:

你正在玩一个战略游戏,你希望为最后的战斗训练最强大的军队。游戏中有N个级别的生物,编号从0到N-1不等。你的军队里已经有了一些生物,你需要花上几天的时间来训练它们。你拥有的生物数量以int[]计数给出。它包含N个元素,第i个元素是一级生物的数量

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

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

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

谁能为我提供解决这个问题需要考虑的子问题?


我还想知道您得出解决方案的思考过程。

它看起来像一个dp,很有趣,我很想尝试一下。。我会这样做:

我创造了一系列不同等级的异能,然后追求升级低于该等级的生物,以获得我能添加的最大异能。我认为这可能是一个贪婪或背包,因为升级哪些是关键决定


edit:我忘了提到你应该如何处理这个数组:你应该对它进行排序以得到排序后的索引。。它实际上更像是一个映射,而不是一个数组,因为您希望在排序过程中洗牌索引,以便知道哪些级别的差异最大,是正的还是负的。。etc

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

解决办法是:

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

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

现在我们可以很容易地编写一个递归解决方案来尝试所有 可能性。当然,我们希望记住计算值 避免指数时间复杂性。要做到这一点,我们需要确定 准确地描述了计算的状态

有两个参数是显而易见的:我们是生物的L级 当前正在升级,剩余天数为D。然而,这是 并非所有,还有一个更重要的问题。我们可能已经做了一些 以前的升级,以及目前的L级生物数量 可能高于输入值。这是第三个区别,, 最后,参数

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

长备忘录[52][102][102];
长计数[52],幂[52];
int N;
长-长解决(整数级、整数添加、长-长升级){
long&res=备忘录[级别][添加][升级];
如果(res>=0)返回res;
res=0;
如果(level==N)返回res;
int maxUpgrades=min(升级、计数[级别]+添加);

对于(int now=0;now你知道你可以检查TopCoder同事提交的代码吗?我最近才知道。我检查了代码,但我无法得到他们正在考虑的子问题是什么,因为他们的变量有随机名称。我已经尝试了这两种方法。这不是贪婪,你可以通过简单的计数器e轻松验证这一点例如,我曾尝试将其转换为背包,但情况不同,因为“重量”的数量不是固定的(你可以将一个生物提升到一个新的级别和相应的“重量”这是背包,不是贪婪的对不起,你只需要升级在升级中给予你正能量的生物,而忘记负能量,如果只有消极的选择,你可以等待,而不训练任何人。值是等级之间的差异。重量将等于你训练该生物达到目标所需的天数在黄金关卡!我不认为这是正确的,我尝试了这种方法。看,在背包中,物体的数量保持不变,但在这种情况下,你的决定改变了物体的数量(重量)。我今天会考虑一个反例。或者你可以在topcoder上编码并测试它。我会惊讶它是否正确,因为我花了相当多的时间将它转换为背包。非常感谢。这个问题困扰了我很长时间。顺便问一下,我在哪里可以找到这些社论?他们有针对每个问题的社论吗?上topcoder站点使用左侧框导航竞赛->算法->单轮比赛->统计->Editorials@deep19我以为你想知道如何解决它,而不是解决方案本身!事实上,这不仅仅是解决方案,
  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);
  }