区间DP,LeetCode 1690. 石子游戏 VII

一、题目

1、题目描述

石子游戏中,爱丽丝和鲍勃轮流进行自己的回合,爱丽丝先开始 。

有 n 块石子排成一排。每个玩家的回合中,可以从行中 移除 最左边的石头或最右边的石头,并获得与该行中剩余石头值之  相等的得分。当没有石头可移除时,得分较高者获胜。

鲍勃发现他总是输掉游戏(可怜的鲍勃,他总是输),所以他决定尽力 减小得分的差值 。爱丽丝的目标是最大限度地 扩大得分的差值 。

给你一个整数数组 stones ,其中 stones[i] 表示 从左边开始 的第 i 个石头的值,如果爱丽丝和鲍勃都 发挥出最佳水平 ,请返回他们 得分的差值 。

2、接口描述

class Solution {
public:
    int stoneGameVII(vector& stones) {

    }
};

3、原题链接

1690. 石子游戏 VII


二、解题报告

1、思路分析

看到1e3数据量想到应该是O(N^2)解法,根据游戏规则不难想到区间dp。

定义f[l][r]为某个玩家先拿手头的情况下,自身得分减去对方得分的最大值。

这样我们会发现,当Alice拿了石头之后,Bob就等效变成了先拿石头的玩家

所以f[l][r] = max(sum(l, r - 1)  + dfs(l, r - 1), sum(l + 1, r) + dfs(l + 1, r))

方程还是很好想的,区间dp板子题属于是

2、复杂度

时间复杂度:O(N^2) 空间复杂度:O(N^2)

3、代码详解

const int N = 1005;
int f[N][N];
class Solution {
public:
    int stoneGameVII(vector& s) {
        int n = s.size();
        for(int i = 1; i < n; i++) s[i] += s[i - 1];
        memset(f, -1, sizeof(f));
        function pre = [&](int i){
            return i >= 0 ? s[i] : 0;
        };
        function dfs = [&](int l, int r){
            if(l >= r) return 0;
            if(~f[l][r]) return f[l][r];
            int& res = f[l][r] = 0;
            res = max(pre(r - 1) - pre(l - 1) - dfs(l, r - 1), pre(r) - pre(l) - dfs(l + 1, r));
            return res;
        };
        return dfs(0, n - 1);
    }
};

你可能感兴趣的:(leetcode每日一题,leetcode,游戏,算法,c++,数据结构,深度优先)