继续撸题!撸一道然后去搞SLAM.
一、题目大意
题目的大致意思是,Petya要参加一场考试,试卷一共n道题,分两种题目,一种是Easy,一种是Hard,对于Easy类题目,Petya需要花费a分钟解决,Hard类题目需要花费b分钟解决,考试一共T分钟。在考试途中,Petya可以随时离开,暂时记离开时间为T1,同时每道题目有一个限定时间,如果T1超过这个限定时间,而且对应的题还没有做出来的话,直接记0分,否则按Petya离开时已经做的题目数量计分。
要求求解Petya在这场考试中最多可以拿到多少分?
二、题目思路以及AC代码
这题的题目思路个人感觉不太好想,但好在样例给的数据涵盖的情况比较全面(可能是过年要发的福利吧)
题目思路大致如下,我们可以考虑Petya不同的离开时间,这里我觉得用一个例子比较好说明。
输入数据:
6 20 2 5
1 1 0 1 0 0
0 8 2 9 11 6
对于这组输入数据,我们肯定想要先把限定时间靠前的一部分工作先做,首先将其按照限定时间从小到大的顺序进行排序(注意要把题目种类一起排序)。
排序之后,我们考虑Petya离开的时间,其实只要不涉及到限定时间,那么我们只需要把简单的题先做,然后做难的题,所得到的答案肯定最大。但是这里要求了限定时间,我们就只需用限定时间区分Petya离开的不同时间即可,是什么意思呢?看我下面的算法步骤。
首先排序之后
5 2 2 5 5 2
0 2 6 8 9 11
这里第一行我直接用了题目花费时间。cur_T表示当前时间,初始为0.
然后我们最初的考虑,直接按这个顺序取就可以了嘛(虽然后来证明并不对),先考虑能不能一道题不做就出去,发现不行,因为第一个的限定时间是0,所以做第一个,cur_T = 5,然后考虑可不可以做完第一题就出去,发现不可以,因为cur_T大于第二个的限定时间,所以必须做第二个,然后再考虑可不可以做完第三题出去,同样cur_T = 7 > 6,也不可以,…,最后发现都不可以,结果是0.
我们发现,我们只需要比较上一个做完的时间,和下一个的限定时间,就决定了我们能不能在上一个题做完之后离开,然后我们需要做的,就是在这些离开的时间点求所能得得最多得分数,再取最大即可。
但这里还有一个问题,不要简单的以为从哪里出去,分数就是前面的几个,我将上面的数据修改一下你就明白了。
5 1 1 5 5 1
0 8 8 8 9 11
这样的话,当我判断可以在做完第一题后就离开,那么我这时离开的最大分数就是1吗?并不是,你会发现,你可以顺便把后面的简单题都做了,因为它并不影响你离开,正确的答案应该是3,第一题再加上之后的两个简单题。
上述就是整道题的思路,个人觉得讲的还是比较清楚的,下面给出AC代码。
AC代码:
/*
* Codeforce 1282C:
* @ Author: Johnson
* @ Date: 2019.12.29
*/
#include <iostream>
#include <algorithm>
#include <vector>
#define MAXN 200010
using namespace std;
struct Problem {
bool type; // false: 简单题 true: 难题
int end_time; // 截至时间
int cost_time;
};
Problem problems[MAXN];
bool cmp(Problem a, Problem b) {
if (a.end_time != b.end_time) return a.end_time < b.end_time;
else return a.cost_time < b.cost_time;
}
int main() {
int m;
cin >> m;
while(m--) {
int n, T, a, b;
cin >> n >> T >> a >> b;
int num_a = 0;
for (int i=1;i<=n;i++) {
cin >> problems[i].type;
if (problems[i].type) problems[i].cost_time = b;
else {
problems[i].cost_time = a;
num_a++;
}
}
for (int i=1;i<=n;i++) {
cin >> problems[i].end_time;
}
// 按照end_time从小到大排序
sort(problems+1, problems+n+1, cmp);
problems[n+1].end_time = T + 1;
long long cur_T = 0;
int score = 0;
for (int i=0;i<=n;i++) {
if (!problems[i+1].type && num_a > 0) num_a--;
if (cur_T < problems[i+1].end_time) {
int diff = problems[i+1].end_time - cur_T - 1;
score = max(score, i + min(static_cast<int>(diff / a), num_a));
}
cur_T += problems[i+1].cost_time;
}
cout << score << endl;
}
return 0;
}
如果有问题,欢迎大家指正!!!