本周周赛的题面风格与以往不太一样,但不要被吓着,读懂题意跟着模拟,其实会发现并不会难到哪里去。

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的更多相关文章

  1. 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)

    Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...

  2. 【LeetCode】208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,Trie, 前缀树,字典树,20 ...

  3. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  4. 【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

    Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653—656) 链接:htt ...

  5. 【Leetcode周赛】从contest-51开始。(一般是10个contest写一篇文章)

    Contest 51 (2018年11月22日,周四早上)(题号681-684) 链接:https://leetcode.com/contest/leetcode-weekly-contest-51 ...

  6. 【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)

    Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest ...

  7. 【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)

    Contest 81 (2018年11月8日,周四,凌晨) 链接:https://leetcode.com/contest/weekly-contest-81 比赛情况记录:结果:3/4, ranki ...

  8. 【Leetcode周赛】从contest-91开始。(一般是10个contest写一篇文章)

    Contest 91 (2018年10月24日,周三) 链接:https://leetcode.com/contest/weekly-contest-91/ 模拟比赛情况记录:第一题柠檬摊的那题6分钟 ...

  9. 【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)

    Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日 ...

随机推荐

  1. python接口自动化测试--数据分离读取Excal指定单元格数据

    上一篇博客讲了怎么批量读取Excal单元格数据,现在咱们说一下怎么读取Excal指定单元格数据. 一.首先建一个Test_Main类 #!/usr/bin/python # -*- coding: U ...

  2. python接口自动化测试--批量读取数据

    为了便于维护,python接口自动化测试用例可以利用xlrd模块读取excal表格进行数据分离.我们可以利用xlrd模块的row_values()和cell_value()两种方法读取Excal表格. ...

  3. 随便聊一聊&最近做的项目

    好久没有发文章了,我并非闲着,而是把原来发博文的形式转成了写稿. 今年是非常特殊的一年,长这么大,从来没有休过如此漫长的寒假,也从未在家进行过一个月以上的远程办公,新冠肺炎对各行各业都产生了巨大影响, ...

  4. 【总结】nginx基础

    一.nginx简介 1.什么是nginx? Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,支持高达 50,000 个并发连接数.功能:反向代理,负载均衡,动静分离 ...

  5. 痞子衡嵌入式:基于恩智浦i.MXRT1060的MP4视频播放器(RT-Mp4Player)设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1062的MP4播放器参考设计. i.MXRT1062是恩智浦i.MXRT四位数系列的中端型号,外设搭配上很均衡,辅以6 ...

  6. 浅谈 Tarjan 算法

    目录 简述 作用 Tarjan 算法 原理 出场人物 图示 代码实现 例题 例题一 例题二 例题三 例题四 例题五 总结 简述 对于初学 Tarjan 的你来说,肯定和我一开始学 Tarjan 一样无 ...

  7. JavaScript的原型对象prototype、原型属性__proto__、原型链和constructor

    先画上一个关系图: 1. 什么是prototype.__proto__.constructor? var arr = new Array; 1. __proto__是原型属性,对象特有的属性,是对象指 ...

  8. 也谈模块加载,吐槽CMD

    先吐槽CMD,不要没头没脑的搞出个CMD,没意思. 大家都看AMD好了,异步模块加载机制,CMD并没有改变这个模式. 模块加载的关口就是getCurrentScript,每次define被调用的时候, ...

  9. Javascript全世界最短的IE判定

    以前最短的IE判定借助于IE不支持垂直制表符的特性搞出来的. var ie=!+'\v'   但这纪录今年1月8日被一个俄国人打破了,现在只要6 bytes!它利用了IE与标准浏览器在处理数组的toS ...

  10. vue-count-to(简单好用的一个数字滚动插件)

    vue-count-to是一个无依赖,轻量级的vue组件,可覆盖easingFn. 1. 你可以设置两个属性startVal和endVal,它会自动判断计数或倒计时.支持vue-ssr.vue-cou ...