Leetcode每日一题:1388. 3n 块披萨(2023.8.18 C++)

目录

1388. 3n 块披萨

问题描述:

实现代码与解析:    

动态规划

原理思路:


1388. 3n 块披萨

问题描述:

给你一个披萨,它由 3n 块不同大小的部分组成,现在你和你的朋友们需要按照如下规则来分披萨:

  • 你挑选 任意 一块披萨。
  • Alice 将会挑选你所选择的披萨逆时针方向的下一块披萨。
  • Bob 将会挑选你所选择的披萨顺时针方向的下一块披萨。
  • 重复上述过程直到没有披萨剩下。

每一块披萨的大小按顺时针方向由循环数组 slices 表示。

请你返回你可以获得的披萨大小总和的最大值。

示例 1:

Leetcode每日一题:1388. 3n 块披萨(2023.8.18 C++)_第1张图片

输入:slices = [1,2,3,4,5,6]
输出:10
解释:选择大小为 4 的披萨,Alice 和 Bob 分别挑选大小为 3 和 5 的披萨。然后你选择大小为 6 的披萨,Alice 和 Bob 分别挑选大小为 2 和 1 的披萨。你获得的披萨总大小为 4 + 6 = 10 。

示例 2:

Leetcode每日一题:1388. 3n 块披萨(2023.8.18 C++)_第2张图片

输入:slices = [8,9,8,6,1,1]
输出:16
解释:两轮都选大小为 8 的披萨。如果你选择大小为 9 的披萨,你的朋友们就会选择大小为 8 的披萨,这种情况下你的总和不是最大的。

提示:

  • 1 <= slices.length <= 500
  • slices.length % 3 == 0
  • 1 <= slices[i] <= 1000

实现代码与解析:    

动态规划

class Solution {
public:
    int dp(vector slices)
    {
        int n = slices.size();
        // f[i][j] 前 i 个披萨中选了 j 个的最大值
        vector> f(n, vector((n + 1) / 3 + 1, 0));

        f[0][0] = 0; // 第 1 个不拿,大小为0
        f[0][1] = slices[0]; // 第一个拿
        f[1][0] = 0; // 第 2 个 不拿
        f[1][1] = max(slices[0], slices[1]);

        for (int i = 2; i < n; i++)
        {
            f[i][0] = 0; // 一个不选是0
            for (int j = 1; j <= (n + 1) / 3; j++)
                f[i][j] = max(f[i - 2][j - 1] + slices[i], f[i - 1][j]);
        }
        
        return f[n - 1][(n + 1) / 3];
    }
    int maxSizeSlices(vector& slices) {

        vector slices1(slices.begin() + 1, slices.end());
        vector slices2(slices.begin(), slices.end() - 1);

        int res1 = dp(slices1);
        int res2 = dp(slices2);

        return max(res1, res2);   
    }
};

原理思路:

        很显然是动态规划的题。

        首先,解析题目含义,也就是选取了一块披萨后,其相邻的披萨不能选取。所以题目就转换成,在n块披萨中选取n / 3个不相邻披萨所能获得的最大值,我们最好在考虑环的问题。

        dp数组 f [ i ][ j ] 含义:从前 i 个披萨中选了 j 个的最大值;

        初始化:因为选取的是不相邻的,所以后一个状态肯定要用到前两个状态,所以我们初始化前两个中的4种状态。

f[0][0] = 0; // 第 1 个不拿,大小为0
f[0][1] = slices[0]; // 第一个拿
f[1][0] = 0; // 第 2 个 不拿
f[1][1] = max(slices[0], slices[1]);

        递推式就很好写了:第 i 个不选,那就取 i 时的最大值即可,选取的,就选 i - 2 时的最大值加上当前披萨的大小即可,两种状态取一个最大值。

f[i][j] = max(f[i - 2][j - 1] + slices[i], f[i - 1][j]);

        最后就是环的处理,考虑两种情况,一种是只考虑第一个,一种是只考虑最后一个,也是最后两种情况取一个最大值即可。

vector slices1(slices.begin() + 1, slices.end());
vector slices2(slices.begin(), slices.end() - 1);

int res1 = dp(slices1);
int res2 = dp(slices2);

return max(res1, res2);  

你可能感兴趣的:(Leetcode,leetcode,c++,算法)