两个马匪分金子

解题思路

考虑先手和后手在序列a(1);a(2);…;a(n)上博弈:
* 如果先手取走了a1,那么问题转为两个人在a(2);a(3);…;a(n)上的博弈
* 如果先手取走了an,问题就变为了在a(1);a(2);…;a(n-1)上的博弈

假设,f(L,R)为两个人在序列a(L);a(L+1);…a(R)上博弈时,先手最多能拿到多少价值,此时后手拿到的
价值一定为:

总价值-f(L,R)

代码

非递归版本动态规划求解

int dp[555][555];
int sum[555];
int main(int argc, char* argv[])
{
  int nums = 0;
  while (cin >> nums)
  {
    if (nums > 0)
    {
      /*nums组测试数据*/
      for (int i = 0; i < nums; i++)
      {
        int numsofdata;//一组数据的个数
        int input;
        int aValue = 0,bValue = 0;
        vector<int> ivec;
        cin >> numsofdata;
        for (int j = 0; j < numsofdata; j++)
        {
          cin >> input;
          ivec.push_back(input);
        }
        if (ivec.size() != numsofdata)
          throw exception("Invalid Input");
        for (size_t k = 1; k <= ivec.size(); k++)
          sum[k] = sum[k-1]+ivec[k-1];
        for (int z = 1; z <= numsofdata; z++)
          dp[z][z] = ivec[z-1];

        for (int m = 1; m <= numsofdata - 1; m++)
        {
          for (int n = 1; n + m <= numsofdata; n++)
          {
            dp[n][n + m] = sum[n + m] - sum[n - 1] - min(dp[n][n + m - 1], dp[n + 1][n + m]);
          }
        }
        aValue = dp[1][numsofdata];
        cout << "Case # " << i + 1 << ":" << aValue << " " << sum[numsofdata] - aValue << endl;
      }
    }
  }

递归版本动态规划求解

int getGolds(vector<int>& golds, int sum)
{
#define MIN(a,b) (((a)>(b))?(b):(a))
  if (golds.size() == 1)return golds[0];

  int leftNum = golds[0];
  vector<int> goldsLeft(golds.begin() + 1, golds.end());

  int rightNum = golds[golds.size() - 1];
  vector<int> goldsRight(golds.begin(), golds.end() - 1);

  return sum - MIN(getGolds(goldsLeft, sum - leftNum), getGolds(goldsRight, sum - rightNum));

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值