给你一个披萨,它由 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. CF1934B Yet Another Coin Problem 题解

    CF1934B Yet Another Coin Problem 题解 题意 目前有 \(5\) 种硬币,面值分别为 \(1,3,6,10,15\).给你一个数字 \(n\),求出可以凑出 \(n\) ...

  2. java进行文件搜索的一个小案例

    分享一个小demo,可以查询某个文件目录下的某个文件并启动,来自黑马的IO教程 import java.io.File; import java.io.IOException; public clas ...

  3. 最好用的截图工具,提取自QQ(带以截图搜图、ocr文字识别,截长图,贴图,色号等功能)

    背景 现在登录QQ比较少,手机的QQ已经具备ocr识别功能,但是电脑上不登陆QQ,微信的简单截图功能又不能进行ocr识别,对于想提取的文字特别麻烦,需要找别的工具去提取.机缘发现网络上这款提取自QQ的 ...

  4. springMvc使用自定义View生成Excel表格

    1:通过自定义的View视图可以让请求直接到一个Excel表去. 2:自定义的视图必须继承  AbstractXlsView /AbstractXlsxView / AbstractXlsxStrea ...

  5. 【REGX】正则表达式 选中空白行

    参考地址: https://www.cnblogs.com/peijyStudy/p/13201576.html VScode并列替换不够智能,我需要等行粘贴,结果SHIFT+ALT复制内容粘贴上去就 ...

  6. 【Hibernate】Re01.5 API

    1.Session单表的CRUD操作 1.增加或者修改,使用同一个方法,或者下面的两个也行: 感觉多此一举... 2.删除方法,硬删除: 3.获取方法提供了两种,Get & Load get方 ...

  7. 【Vue】11 VueRouter Part1 概述 & 入门

    什么是路由? 即通过互联网把信息从源地址传输到目的地址的活动 路由决定数据包从来源到目的地的路径 转送将输入端的数据转移到合适的输出端 后端路由: 早起网站开发全部由服务器渲染,例如 Java的JSP ...

  8. 树莓派3b+ 安装Ubuntu mate18.04系统 配置SSH 、 远程桌面realvnc

    Ubuntu mate  for  树莓派3b+ 系统下载: 下载地址: https://ubuntu-mate.org/download/ 这里用32位系统:(64位也可以的,虽然还是实验阶段的,不 ...

  9. 生态兼容性进一步提升!白鲸开源 WhaleStudio 与火山引擎ByteHouse完成产品互认

    数据作为新型生产要素,已快速融入生产.分配.流通.消费和社会服务管理等各环节,深刻改变着生产方式.生活方式和治理方式.越来越多企业也在尝试充分利用数据要素,开辟全新发展路径,进一步实现业务价值提升. ...

  10. 【全】CSS动画大全之404页面【a】

    效果预览 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...