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

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

本文关键字:提取 角落 总价值 一条      更新时间:2023-10-16

考虑下面的游戏。

经销商产生序列s1…Sn张牌,面朝上每张牌si都有一个值vi。然后两名玩家轮流从序列中取出一张牌,但是只能选择RST或(剩余)序列的最后一张牌。目标是收集卡片最大总价值。(例如,你可以把卡片想象成不同面值的钞票。)

给出一个O(n^2)算法来计算第一个参与人的最优策略(只是最大可获得的代码)。

我已经尝试解决它的合法和可能解决它这里是我的代码…数组cards包含每张卡的值。卡片的第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("%dn",(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]

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