【贪心】P11112 [ROI 2024] 机器人物流 (Day 1)|普及+
本文涉及知识点
C++贪心
P11112 [ROI 2024] 机器人物流 (Day 1)
题目背景
翻译自 ROI 2024 D1T1。
在 ROI 2224 举办之时,一群能够克隆自身的机器人负责送货。人们不用出门,可以直接通过窗户拿到货物。
最开始只有一个送货机器人。在任何时候,最上面的机器人可以在自己上方克隆出一个或多个新的机器人,形成一个“机器人柱”。每个机器人的高度等于一层楼。
在送货过程中,机器人柱会沿着宿舍楼从左到右移动。机器人的数据库中包含了订单列表,每个订单都指定了一个需要送货的窗户。当机器人队列经过一个窗户时,如果队列中有机器人位于窗户所在的高度,则可以直接完成送货。
在移动过程中,机器人柱可能会碰到障碍物。碰到障碍物后,只有位于障碍物高度上方的机器人能够继续移动。这些机器人在经过障碍物后会立刻重新排成一个机器人柱,并且可以继续移动、克隆和完成送货任务。
障碍物和窗户之间的距离足够大,因此机器人在经过障碍物时不会同时经过窗户。
题目描述
每完成一个订单,机器人公司会获得 ppp 个虚拟货币,而克隆一个新机器人的成本是 ccc 个虚拟货币。最终利润等于订单配送的总收入减去所有机器人克隆的总成本。公司希望最大化利润。请你确定公司可以获得的最大利润。
公司不需要完成所有订单,且机器人可以在任何时候停止送货。
输入格式
第一行包含四个整数 n,m,c,pn, m, c, pn,m,c,p(0≤n,m≤1000000 \le n, m \le 1000000≤n,m≤100000,1≤c,p≤10000001 \le c, p \le 10000001≤c,p≤1000000),分别表示障碍物的数量、订单的数量、克隆一个机器人的成本和每个订单的配送收入。
接下来的 n+mn + mn+m 行描述了障碍物和窗户的详细信息,按从左到右的顺序给出。每行包含两个整数 tit_iti 和 hih_ihi(1≤ti≤21 \le t_i \le 21≤ti≤2,1≤hi≤10000001 \le h_i \le 10000001≤hi≤1000000),其中 tit_iti 表示对象的类型(111 为障碍物,222 为窗户),hih_ihi 表示障碍物的高度或窗户所在的楼层。
保证有 nnn 个障碍物,剩余 mmm 个为窗户。
输出格式
输出一个整数,表示可以获得的最大利润。
输入输出样例 #1
输入 #1
2 3 2 6
1 2
2 3
1 1
2 6
2 2
输出 #1
4
输入输出样例 #2
输入 #2
1 3 1 5
2 2
2 1
1 9
2 1
输出 #2
9
说明/提示
样例 111 解释:
以下是订单配送的最佳策略之一,如果选择配送到第二个窗户,不会增加公司的利润。
样例 222 解释:
只需要克隆一次机器人,用来配送到第一个窗户,因为这个新克隆的机器人可以继续用来配送到第二个窗户。为了配送到第三个窗户而进行额外的克隆在经济上是不划算的。
下面是各个子任务的分值和特殊性质表格。全部数据范围见输入格式。
子任务 | 分值 | 特殊性质 |
---|---|---|
111 | 242424 | n≤100,m≤100,hi≤100n\le100,m\le100,h_i\le100n≤100,m≤100,hi≤100 |
222 | 121212 | n=0n=0n=0 |
333 | 141414 | n=1n=1n=1 |
444 | 151515 | m=1m=1m=1 |
555 | 171717 | c=1,p=106c=1,p=10^6c=1,p=106 且障碍物高度均为 111 |
666 | 181818 | 无 |
贪心
完成订单P的充要条件:机器人数量≥hi+它左边障碍之和\ge h_i+它左边障碍之和≥hi+它左边障碍之和
实现
long long sum 记录[0,i)中障碍物之和。v记录各任务需要的机器人数量。
i = 0 to N-1
如果是障碍物 sum+=hi否则v.Add(sum+hi)sum+= h_i 否则 v.Add(sum+h_i)sum+=hi否则v.Add(sum+hi)
v升序排序。
max(p×(i+1)−c×(v[i]−1)\max(p \times (i+1) - c \times (v[i]-1)max(p×(i+1)−c×(v[i]−1)
注意: 初始机器人是免费的。
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include<list>
#include<array>#include <bitset>
#include <chrono>
using namespace std::chrono;
using namespace std;template<class T1, class T2>
std::istream& operator >> (std::istream& in, pair<T1, T2>& pr) {in >> pr.first >> pr.second;return in;
}template<class T1, class T2, class T3 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t);return in;
}template<class T1, class T2, class T3, class T4 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t);return in;
}template<class T1, class T2, class T3, class T4, class T5, class T6, class T7 >
std::istream& operator >> (std::istream& in, tuple<T1, T2, T3, T4, T5, T6, T7>& t) {in >> get<0>(t) >> get<1>(t) >> get<2>(t) >> get<3>(t) >> get<4>(t) >> get<5>(t) >> get<6>(t);return in;
}template<class T = int>
vector<T> Read() {int n;cin >> n;vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}
template<class T = int>
vector<T> ReadNotNum() {vector<T> ret;T tmp;while (cin >> tmp) {ret.emplace_back(tmp);if ('\n' == cin.get()) { break; }}return ret;
}template<class T = int>
vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {cin >> ret[i];}return ret;
}template<int N = 1'000'000>
class COutBuff
{
public:COutBuff() {m_p = puffer;}template<class T>void write(T x) {int num[28], sp = 0;if (x < 0)*m_p++ = '-', x = -x;if (!x)*m_p++ = 48;while (x)num[++sp] = x % 10, x /= 10;while (sp)*m_p++ = num[sp--] + 48;AuotToFile();}void writestr(const char* sz) {strcpy(m_p, sz);m_p += strlen(sz);AuotToFile();}inline void write(char ch){*m_p++ = ch;AuotToFile();}inline void ToFile() {fwrite(puffer, 1, m_p - puffer, stdout);m_p = puffer;}~COutBuff() {ToFile();}
private:inline void AuotToFile() {if (m_p - puffer > N - 100) {ToFile();}}char puffer[N], * m_p;
};template<int N = 1'000'000>
class CInBuff
{
public:inline CInBuff() {}inline CInBuff<N>& operator>>(char& ch) {FileToBuf();while (('\r' == *S) || ('\n' == *S) || (' ' == *S)) { S++; }//忽略空格和回车ch = *S++;return *this;}inline CInBuff<N>& operator>>(int& val) {FileToBuf();int x(0), f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行 return *this;}inline CInBuff& operator>>(long long& val) {FileToBuf();long long x(0); int f(0);while (!isdigit(*S))f |= (*S++ == '-');while (isdigit(*S))x = (x << 1) + (x << 3) + (*S++ ^ 48);val = f ? -x : x; S++;//忽略空格换行return *this;}template<class T1, class T2>inline CInBuff& operator>>(pair<T1, T2>& val) {*this >> val.first >> val.second;return *this;}template<class T1, class T2, class T3>inline CInBuff& operator>>(tuple<T1, T2, T3>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val);return *this;}template<class T1, class T2, class T3, class T4>inline CInBuff& operator>>(tuple<T1, T2, T3, T4>& val) {*this >> get<0>(val) >> get<1>(val) >> get<2>(val) >> get<3>(val);return *this;}template<class T = int>inline CInBuff& operator>>(vector<T>& val) {int n;*this >> n;val.resize(n);for (int i = 0; i < n; i++) {*this >> val[i];}return *this;}template<class T = int>vector<T> Read(int n) {vector<T> ret(n);for (int i = 0; i < n; i++) {*this >> ret[i];}return ret;}template<class T = int>vector<T> Read() {vector<T> ret;*this >> ret;return ret;}
private:inline void FileToBuf() {const int canRead = m_iWritePos - (S - buffer);if (canRead >= 100) { return; }if (m_bFinish) { return; }for (int i = 0; i < canRead; i++){buffer[i] = S[i];//memcpy出错 }m_iWritePos = canRead;buffer[m_iWritePos] = 0;S = buffer;int readCnt = fread(buffer + m_iWritePos, 1, N - m_iWritePos, stdin);if (readCnt <= 0) { m_bFinish = true; return; }m_iWritePos += readCnt;buffer[m_iWritePos] = 0;S = buffer;}int m_iWritePos = 0; bool m_bFinish = false;char buffer[N + 10], * S = buffer;
};class Solution {
public:long long Ans(long long c, long long p, vector<pair<int, int>>& as) {long long sum = 0;vector<long long> v;for (const auto& [kind, h] : as) {if (1 == kind) {sum += h;}else {v.emplace_back(sum + h);}}sort(v.begin(), v.end());long long ans = 0;for (int i = 0; i < v.size(); i++) {const long long cur = p * (i + 1) - c * (v[i] - 1);ans = max(ans, cur);}return ans;}
};
int main() {
#ifdef _DEBUGfreopen("a.in", "r", stdin);
#endif // DEBUG ios::sync_with_stdio(0); cin.tie(nullptr);//CInBuff<> in; COutBuff<10'000'000> ob;int n, m;long long c, p;cin >> n>> m >> c >> p ;auto as = Read<pair<int, int>>(n+m);
#ifdef _DEBUG printf("c=%lld,p=%lld", c,p);Out(as, ",as=");//Out(ps, ",ps=");//Out(ss, ",ss=");//Out(que, ",ope=");
#endif // DEBUG auto res = Solution().Ans(c,p,as);cout << res << "\n";return 0;
}
单元测试
long long c, p;vector<pair<int, int>> as;TEST_METHOD(TestMethod01){c = 2, p = 6, as = { {1,2},{2,3},{1,1},{2,6},{2,2} };auto res = Solution().Ans(c, p, as);AssertEx(4LL, res);}TEST_METHOD(TestMethod02){c = 1, p = 5, as = { {2,2},{2,1},{1,9},{2,1} };auto res = Solution().Ans(c, p, as);AssertEx(9LL, res);}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。