LeetCode周赛#208
本周周赛的题面风格与以往不太一样,但不要被吓着,读懂题意跟着模拟,其实会发现并不会难到哪里去。
1599. 经营摩天轮的最大利润 #模拟
题目链接
题意
摩天轮\(4\)个座舱,每个座舱最多可容纳\(4\)位游客,座舱会轮转,且每次轮转需支付一定运行成本\(runningCost\),且恰好转动\(1/4\)周。
给定长度为\(n\)的数组\(customers\), \(customers[i]\) 是在第 \(i\) 次轮转之前到达的新游客的数量,即你必须在新游客到来前轮转\(i\) 次。每位游客在登上离地面最近的座舱前都会支付登舱成本 \(boardingCost\) ,一旦该座舱再次抵达地面,他们就会离开座舱结束游玩。注意,如果有超过 4 位游客在等摩天轮,那么只有 恰好4 位游客可以登上摩天轮,其余的需要等待 下一次轮转 。你需要返回最大化利润所需执行的 最小轮转次数 。 如果不存在利润为正的方案,则返回 \(-1\)。
样例
分析
利用队列去模拟摩天轮的四个舱位,之所以用队列,是因为该四个舱位的出现存在顺序,先来的游客便先获得机会登上座舱。但注意,每个座舱不一定坐满乘客!
class Solution {
private:
queue<int> motian;
public:
int minOperationsMaxProfit(vector<int>& customers, int boardingCost, int runningCost) {
int last = 0, cur = 0, bonus = 0; //last表示当前等待中的游客数,cur表示摩天轮上登上舱的总人数,bonus表示利润
int i = 0, ans = -0x3f3f3f3f, pos = -1; //pos表示取得最值时的操作次数
while(last != 0 || i < customers.size()){
if(i < customers.size()) last += customers[i];
if(last <= 4){
cur += last;
motian.push(last);
last = 0;
}
else {
cur += 4;
motian.push(4);
last -= 4;
}
bonus = boardingCost * cur - runningCost * motian.size();
if(ans < bonus){
ans = bonus; pos = i;
}
i++;
}
return (ans <= 0) ? -1 : pos + 1;
}
};
1600. 皇位继承顺序 #C++类 #多叉树的先序遍历
题目链接
题意
题目看起来很长,简要概括为:
王国里住国王、其孩子们、孙子们等等。每一时间点,该家庭里有人出生或死亡。王国有皇位继承顺序,第一继承人总是国王自己,第二继承人为其最年长的儿子,第三继承人为该儿子的儿子,… ,直至没有后代了,再有继承人为国王第二个儿子,….,依次类推。
现要你实现 ThroneInheritance
类:
ThroneInheritance(string kingName);
初始化一个ThroneInheritance
类的对象。国王的名字作为构造函数的参数传入。void birth(string parentName, string childName);
表示parentName
新拥有了一个名为childName
的孩子。void death(string name);
表示名为name
的人死亡。一个人的死亡不会影响Successor
函数,也不会影响当前的继承顺序。你可以只将这个人标记为死亡状态。string[] getInheritanceOrder()
返回除去死亡人员的当前继承顺序列表。
分析
每个人都可能有多个或没有孩子,我们可以将用多叉树的结构去模拟;对于继承顺序,我们不难看出,实际就是多叉树的先序遍历,每次继承的是其第一个后代!由于数据规模不大,且加入新节点都是以string
作为参数,于是我们用string
映射含有多个string
的向量。
const int MAXN = 1e5 + 5;
class ThroneInheritance {
private:
string king;
unordered_map<string, bool> isDeath; //名字映射布尔值,表示某个人是否死亡
unordered_map<string, vector<string>> Order; //第一个key,映射一个vector,表示名字为key的后代存在vector中
public:
ThroneInheritance(string kingName) {
king = kingName;
isDeath[kingName] = false;
}
void birth(string parentName, string childName) {
Order[parentName].push_back(childName);
isDeath[childName] = false;
}
void death(string name) {
isDeath[name] = true;
}
void Successor(string cur, vector<string>& ans){ //利用DFS,确定继承
int i = 0;
for(int i = 0; i < Order[cur].size(); i++){
string son = Order[cur][i];
if(isDeath[son] == false) ans.push_back(son);
Successor(son, ans);
}
}
vector<string> getInheritanceOrder() {
string cur = king;
vector<string> ans;
if(isDeath[king] == false) ans.push_back(king);
Successor(cur, ans);
return ans;
}
};
1601.最多可达成的换楼请求数目 #枚举子集 #回溯+剪枝
题目链接
题意
$n $栋楼,编号从 \(0\) 到 \(n - 1\) 。每栋楼有若干员工。部分员工想换一栋楼居住。给定数组\(requests(requests.size()\leq16)\) ,其中$ requests[i] = [from_i, to_i]$ ,表示一个员工请求从编号为 \(from_i\) 的楼搬到编号为 \(to_i\) 的楼。
一开始所有楼都是满的,所以从请求列表中选出的若干个请求是可行的需要满足 每栋楼员工净变化为\(0\) 。意思是每栋楼离开的员工数目 等于 该楼 搬入的员工数数目。比方说 \(n = 3\) 且两个员工要离开楼 \(0\) ,一个员工要离开楼 \(1\) ,一个员工要离开楼 2 ,如果该请求列表可行,应该要有两个员工搬入楼 \(0\) ,一个员工搬入楼 \(1\) ,一个员工搬入楼$ 2$ 。
请你从原请求列表中选出若干个请求,使得它们是一个可行的请求列表,并返回所有可行列表中最大请求数目。
分析
Solution1 : 枚举子集
由于\(requests\)数组最大长度为\(16\),即总共有\(16\)条边,那么我们可以枚举选中某些边、不选某些边,共有\(1<<16 = 65536\),由此计算出所有楼的度数是否为\(0\),若为\(0\)说明入度等于出度,满足题意,更新最值;若不为\(0\),则不可行。接下来我们将所有边的选择状态用一二进制去记录,然后枚举这个二进制数,内层再枚举该二进制数的子集即可。时间略慢,约\(440ms\)
class Solution {
public:
int maximumRequests(int n, vector<vector<int>>& requests) {
int ans = -1;
int mymax = requests.size();
for (int state = 0; state < (1 << mymax); state++){ //枚举状态
int inD[22] = {0}, outD[22] = {0};
int cnt = 0;
for(int j = 0; j < mymax; j++){ //枚举子集
if(state & (1 << j)){
outD[requests[j][0]]++;
inD[requests[j][1]]++;
cnt++;
}
}
bool f = true;
for (int i = 0; i < n; i++){
if(inD[i] != outD[i]) {
f = false;
break;
}
}
if(f) ans = max(ans, cnt);
}
return ans;
}
};
Solution2 : 深搜回溯+剪枝
时间为\(84ms\)
class Solution {
private:
int degree[20];
int ans = -1;
public:
void DFS(int start, vector<vector<int>>& requests, int sum, int n){
if(start == requests.size()){
for (int i = 0; i < n; i++)
if(degree[i] != 0) return;
ans = max(sum, ans);
}
else if((int)requests.size() - start + 1 + sum < ans) //常见剪枝方式
return;
else {
DFS(start + 1, requests, sum, n); //不选第start条边
degree[requests[start][0]]--;
degree[requests[start][1]]++;
DFS(start + 1, requests, sum + 1, n); //选中第start条边
degree[requests[start][0]]++;
degree[requests[start][1]]--;
}
}
int maximumRequests(int n, vector<vector<int>>& requests) {
DFS(0, requests, 0, n);
return ans;
}
};
LeetCode周赛#208的更多相关文章
- 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)
Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...
- 【LeetCode】208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,Trie, 前缀树,字典树,20 ...
- 拼写单词[哈希表]----leetcode周赛150_1001
题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...
- 【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)
Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653—656) 链接:htt ...
- 【Leetcode周赛】从contest-51开始。(一般是10个contest写一篇文章)
Contest 51 (2018年11月22日,周四早上)(题号681-684) 链接:https://leetcode.com/contest/leetcode-weekly-contest-51 ...
- 【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)
Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest ...
- 【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)
Contest 81 (2018年11月8日,周四,凌晨) 链接:https://leetcode.com/contest/weekly-contest-81 比赛情况记录:结果:3/4, ranki ...
- 【Leetcode周赛】从contest-91开始。(一般是10个contest写一篇文章)
Contest 91 (2018年10月24日,周三) 链接:https://leetcode.com/contest/weekly-contest-91/ 模拟比赛情况记录:第一题柠檬摊的那题6分钟 ...
- 【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)
Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日 ...
随机推荐
- python接口自动化测试--数据分离读取Excal指定单元格数据
上一篇博客讲了怎么批量读取Excal单元格数据,现在咱们说一下怎么读取Excal指定单元格数据. 一.首先建一个Test_Main类 #!/usr/bin/python # -*- coding: U ...
- python接口自动化测试--批量读取数据
为了便于维护,python接口自动化测试用例可以利用xlrd模块读取excal表格进行数据分离.我们可以利用xlrd模块的row_values()和cell_value()两种方法读取Excal表格. ...
- 随便聊一聊&最近做的项目
好久没有发文章了,我并非闲着,而是把原来发博文的形式转成了写稿. 今年是非常特殊的一年,长这么大,从来没有休过如此漫长的寒假,也从未在家进行过一个月以上的远程办公,新冠肺炎对各行各业都产生了巨大影响, ...
- 【总结】nginx基础
一.nginx简介 1.什么是nginx? Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,支持高达 50,000 个并发连接数.功能:反向代理,负载均衡,动静分离 ...
- 痞子衡嵌入式:基于恩智浦i.MXRT1060的MP4视频播放器(RT-Mp4Player)设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1062的MP4播放器参考设计. i.MXRT1062是恩智浦i.MXRT四位数系列的中端型号,外设搭配上很均衡,辅以6 ...
- 浅谈 Tarjan 算法
目录 简述 作用 Tarjan 算法 原理 出场人物 图示 代码实现 例题 例题一 例题二 例题三 例题四 例题五 总结 简述 对于初学 Tarjan 的你来说,肯定和我一开始学 Tarjan 一样无 ...
- JavaScript的原型对象prototype、原型属性__proto__、原型链和constructor
先画上一个关系图: 1. 什么是prototype.__proto__.constructor? var arr = new Array; 1. __proto__是原型属性,对象特有的属性,是对象指 ...
- 也谈模块加载,吐槽CMD
先吐槽CMD,不要没头没脑的搞出个CMD,没意思. 大家都看AMD好了,异步模块加载机制,CMD并没有改变这个模式. 模块加载的关口就是getCurrentScript,每次define被调用的时候, ...
- Javascript全世界最短的IE判定
以前最短的IE判定借助于IE不支持垂直制表符的特性搞出来的. var ie=!+'\v' 但这纪录今年1月8日被一个俄国人打破了,现在只要6 bytes!它利用了IE与标准浏览器在处理数组的toS ...
- vue-count-to(简单好用的一个数字滚动插件)
vue-count-to是一个无依赖,轻量级的vue组件,可覆盖easingFn. 1. 你可以设置两个属性startVal和endVal,它会自动判断计数或倒计时.支持vue-ssr.vue-cou ...