收集保持在一条线上时总价值最大的卡片(仅从角落提取)

Collect cards of largest total value when kept in a line (extraction only from the corners)

考虑以下游戏。

一位庄家发出了一系列 s1 ...sn 牌,面朝上,其中 每张卡片 si 都有一个值 vi。然后两名玩家轮流从序列中挑选一张牌,但是 只能挑选(剩余)序列的第一张或最后一张牌。目标是收集卡片 总价值最大。 (例如,你可以把卡片想象成不同面额的钞票。)

给出一个复杂度为 O(n^2) 的算法来计算第一个玩家的最优策略(只是最大可获得的代码)。

我试过顺路解决它,可能解决了这是我的代码... 数组卡片具有每张卡片的值。卡片的第 0 个元素未使用且浪费(基本索引 1)!

  #include<bits/stdc++.h>
  using namespace std;
  int main()
  {
   int cards[]={0,2,100,101,1};
   int n=4;
   int i,j,l,sum=204;
   int dp[n+1][n+1];
   memset(dp,0,sizeof(dp));
   for(i=1;i<=n;i++)
      dp[i][i]=cards[i];
   for(l=2;l<=n;l++)
   {
      for(i=1;i<=n-l+1;i++)
              {
                  j=i+l-1;
                  dp[i][j]=max(cards[i]-dp[i+1][j],cards[j]-dp[i][j-1]);
               }
    }
    printf("%d\n",(sum+dp[1][n])/2);

    return 0;
    }

在最后的打印语句中,我打印了(sum+dp[1][n])/2,因为元素是2n,所以当我做这个操作时,n将被包括在内,其余的n将被减去,我得到包含值的总和。

虽然它给出了正确答案,但我仍然无法说出 dp[i][j] 到底代表什么!!它不代表可获得的最大价值(因为它不会直接给我那个价值)。 那么我的另一个问题是什么意思??

有没有其他思路可以解决这样的问题?

在您发布的代码中,dp[i][j] 代表第一个和第二个玩家可以从子字符串 i..j 开始获得的最大点数差异:dp[i][j]=max(first[i][j]-second[i][j])(这是不是编程语言公式,只是为了给出想法),这里我们称第一个玩家为从该位置开始的玩家。

所以考虑一个子串i..j。第一个玩家 (A) 可以选择拿第一张或最后一张牌。如果他拿了第一张牌,他会得到 cards[i],但是他的对手 (B) 将从子串 i+1..j 开始。他会竭尽全力,在他的人情中得到差价dp[i+1][j],也就是差价会pointsB - pointsA = dp[i+1][j]。但是对于我们的位置i,j,我们对差异pointsA-pointsB感兴趣,所以我们取-dp[i+1][j]并记住取的card[i],因此

dp[i][j]=card[i]-dp[i+1][j]

还有一种变体,就是取最后一张牌,结果为

dp[i][j]=card[j]-dp[i][j+1]

显然,玩家会选择最好的选项,因此您应该取两个值中的最大值。