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

你挑选 任意 一块披萨。
Alice 将会挑选你所选择的披萨逆时针方向的下一块披萨。
Bob 将会挑选你所选择的披萨顺时针方向的下一块披萨。
重复上述过程直到没有披萨剩下。
每一块披萨的大小按顺时针方向由循环数组 slices 表示。

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

示例 1:

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

这条比较难的一点是论证:

题目可以转换为,取任意 n/3 个不相邻的数字的最大和。

1、首先显然相邻的两个数字是不可能同时取到的。

2、任意长度为 n/3 的不相邻的子序列都可以被取到。

  尝试简单论证一下,

  用0表示不选择,1表示选择,当选择不相邻的n/3个数字之后,001001001 这样的序列可以表示为一种选取方法。

  显然,存在某个1的周围有至少三个0,如 0010 或 0100 (由于是一个圆 首尾时相连接的)

  因为如果不存在的话,则序列只能为 010101... 显然 1 的个数会大于 n/3

  然后先选取这样的 1 和周围的两个 0 ,那么,剩下还是会有一个 0,(不会出现两个1相邻)

  则剩下的序列还是满足最开始的条件,继续以同样的规则选择直到结束最后剩下010。

  举例说明:

  001010100

  先取第一个1和旁边的0 变为 010100

  取后面的1和旁边的0 变为 010 最后全部取走。

如果能想到上面的结论,剩下的就只是一个简单的DP了,DP[i][j] 表示取i块,最后一块序列为j的最大值,由于第一块和最后一块不能同时取,所以需要计算两次。其实和这道题蛮像的 https://leetcode-cn.com/problems/house-robber-ii/

class Solution {
public:
int maxSizeSlices(vector<int>& slices) {
int n = slices.size();
int select = n / 3;
int dp1[select + 1][n];
int dp2[select + 1][n];
memset(dp1, 0, sizeof dp1);
memset(dp2, 0, sizeof dp2);
dp1[1][0] = slices[0];
dp2[1][1] = slices[1];
for (int i = 1; i <= select; i++) {
for (int j = 2; j < n; j++) {
for (int k = 0; k < j - 1; k++) {
dp1[i][j] = max(dp1[i][j], dp1[i-1][k] + slices[j]);
dp2[i][j] = max(dp2[i][j], dp2[i-1][k] + slices[j]);
}
}
}
int ans = 0;
for (int i = 0; i < n - 1; i++) {
ans = max(ans, dp1[select][i]);
}
for (int i = 0; i < n; i++) {
ans = max(ans, dp2[select][i]);
}
return ans;
}
};

三层循环可以简化为两层循环

class Solution {
public:
int maxSizeSlices(vector<int>& slices) {
int n = slices.size();
int select = n / 3;
int dp1[select + 1][n];
int dp2[select + 1][n];
memset(dp1, 0, sizeof dp1);
memset(dp2, 0, sizeof dp2);
dp1[1][0] = slices[0];
dp2[1][1] = slices[1];
int max1, max2;
for (int i = 1; i <= select; i++) {
max1 = dp1[i-1][0];
max2 = dp2[i-1][0];
for (int j = 2; j < n; j++) {
dp1[i][j] = max1 + slices[j];
dp2[i][j] = max2 + slices[j];
max1 = max(max1, dp1[i-1][j-1]);
max2 = max(max2, dp2[i-1][j-1]);
}
}
int ans = 0;
for (int i = 0; i < n - 1; i++) {
ans = max(ans, dp1[select][i]);
}
for (int i = 0; i < n; i++) {
ans = max(ans, dp2[select][i]);
}
return ans;
}
};

LeetCode 1388. Pizza With 3n Slices(3n 块披萨)(DP)的更多相关文章

  1. 动态规划-不连续最大子序列和-打家劫舍系列-1388. 3n 块披萨

    2020-03-24 17:49:58 198. 打家劫舍 问题描述: 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统, ...

  2. Java实现 LeetCode 769 最多能完成排序的块(单向遍历)

    769. 最多能完成排序的块 数组arr是[0, 1, -, arr.length - 1]的一种排列,我们将这个数组分割成几个"块",并将这些块分别进行排序.之后再连接起来,使得 ...

  3. Java实现 LeetCode 768 最多能完成排序的块 II(左右便利)

    768. 最多能完成排序的块 II 这个问题和"最多能完成排序的块"相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8. arr是一个可能包含 ...

  4. Leetcode 详解(股票交易日)(动态规划DP)

    问题描述: 在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于2),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行).给出一天中的股票变化序列,请写一个程序计算一天可以获得 ...

  5. Leetcode: Combination Sum IV && Summary: The Key to Solve DP

    Given an integer array with all positive numbers and no duplicates, find the number of possible comb ...

  6. leetcode 201. Bitwise AND of Numbers Range(位运算,dp)

    Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers ...

  7. 第十六周 Leetcode 600. Non-negative Integers without Consecutive Ones(HARD) 计数dp

    Leetcode600 很简单的一道计数题 给定整数n 求不大于n的正整数中 二进制表示没有连续的1的数字个数 在dp过程中只要保证不出现连续1以及大于n的情况即可. 所以设计按位dp[i][j]表示 ...

  8. LeetCode 1223. 掷骰子模拟 Dice Roll Simulation - Java - DP

    题目链接:1223. 掷骰子模拟 有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数. 不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[ ...

  9. Java实现 LeetCode 813 最大平均值和的分组 (DFS+DP记忆化搜索)

    813. 最大平均值和的分组 我们将给定的数组 A 分成 K 个相邻的非空子数组 ,我们的分数由每个子数组内的平均值的总和构成.计算我们所能得到的最大分数是多少. 注意我们必须使用 A 数组中的每一个 ...

  10. Leetcode 137.只出现一次的数字II

    只出现一次的数字II 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? ...

随机推荐

  1. 关于写作那些事之快速上手Mermaid流程图

    本文主要介绍了如何快速上手 Mermaid 流程图,不用贴图上传也不用拖拉点拽绘制,基于源码实时渲染流程图,操作简单易上手,广泛被集成于主流编辑器,包括 markdown 写作环境. 通过本节内容你将 ...

  2. 【超实用攻略】SpringBoot + validator 轻松实现全注解式的参数校验

    一.故事背景 关于参数合法性验证的重要性就不多说了,即使前端对参数做了基本验证,后端依然也需要进行验证,以防不合规的数据直接进入服务器,如果不对其进行拦截,严重的甚至会造成系统直接崩溃! 本文结合自己 ...

  3. CF1988C Increasing Sequence with Fixed OR Solution

    题意简述如下: 给定一个正整数 \(n\),请构造一个正整数序列使其满足以下条件并尽可能长:这个序列中每个数都大于等于 \(1\) 且小于等于\(n\):这个序列是单调递增的:这个序列中任意两个相邻的 ...

  4. ChatGPT的作用(附示例)

    ChatGPT介绍(内容由ChatGPT生成) ChatGPT是一款基于GPT(生成式预测网络)的聊天机器人,它可以根据用户输入自动生成相应的回复. GPT是由OpenAI开发的一种预测网络模型,其中 ...

  5. java开发环境安装IDEA+jdk1.8

    一. 需要得安装包 (1)IDEA破解版.zip (2)jdk1.8.0_25.7z 获取方式(免费): (1)       登录-注册:http://resources.kittytiger.cn/ ...

  6. 对比python学julia(第四章:人工智能)--(第四节)绘画大师

    1.1.  项目简介 所谓图像风格迁移,是利用深度学习技术,将一幅风格图像输人卷积神经网络提取风格特征,再将其应用到另一幅内容图像上,从而生成一幅与风格囝像相仿的新图像.如果选取绘画大师的作品作为风格 ...

  7. 【MacOS】VMware安装10.15-Catalina版本

    参考自: https://www.bilibili.com/video/BV1sf4y1D77A?p=4 资源地址: https://pan.baidu.com/s/1U6WOorb_TuORQ9ab ...

  8. python报错:`visualize_sharding` requires `rich` to be installed.

    Rich是python的一个绘图library,需要手动安装. 解决方法: pip install Rich

  9. .NET电子邮件高效处理解决方案

    前言 在日常软件开发中,电子邮件处理是一个不可或缺的功能,无论是用户注册验证.通知推送还是日常的业务沟通,都离不开电子邮件的支持.今天大姚给大家分享2款.NET开源.高效.强大的.NET电子邮件处理库 ...

  10. 7月新特性 | 软件开发生产线CodeArts发布多项新特性等你体验!

    华为云软件开发生产线CodeArts是一站式.全流程.安全可信的云原生DevSecOps平台,覆盖需求.开发.测试.部署.运维等软件交付全生命周期环节,为开发者打造全云化研发体验.2024年7月,Co ...