自己写了两个版本。。。但是总是超时,这种题目选好合适的数据结构很重要
// 使用vector保存信息
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n, m, k;
vector<pair<int, int>> record;
bool not_equal_k(vector<pair<int, int>> a, int k) {
for(auto x: a) {
if(x.first != k) {
return true;
}
}
return false;
}
bool same(vector<pair<int, int>> a) {
int T = a[0].first;
for (int i = 1; i < n; i ++ ) {
if(a[i].first != T) {
return false;
}
}
return true;
}
static bool cmp(const pair<int, int>& v1, const pair<int, int>& v2){
//如果第一元素相等,则比较第二元素
if (v1.first == v2.first)
return v1.second < v2.second;
return v1.first > v2.first;
}
int find(vector<pair<int, int>> a, int T) {
int s = a.size();
for(int i = 0; i < s; i ++) {
if(a[i].first == T) return i;
}
return -1;
}
int find_max(vector<pair<int, int>> a) {
int idx = 0;
int s = a.size();
int mx = a[0].first;
for (int i = 1; i < s; i ++ ) {
if(record[i].first > mx) {
mx = record[i].first;
idx = i;
}
}
return idx;
}
int main()
{
cin >> n >> m >> k;
int all = 0;
int t, c;
cin >> t >> c;
record.push_back({t, c});
// 做法不确定是否正确并且超时了,我们在读入数据的时候把初始所需时间一样的归为一类
for (int i = 1; i < n; i ++ ) {
cin >> t >> c;
int idx = find(record, t);
if(idx == -1) record.push_back({t, c});
else record[idx].second += c;
all += c;
}
sort(record.begin(), record.end(), cmp);
bool not_all_k = true;
bool can_lower = true;
// for (int i = 0; i < record.size(); i ++ ) {
// cout << record[i].first <<" " << record[i].second<< endl;
// }
// 退出的条件是
// 1. 资源耗尽(m == 0)
// 2. 无法再将所有的工程(此时已经全部是同一个数字)全部减少一天
// 3. 所有工程的天数都已经为k
int i = 0;
if(m > 10000 * all) {
cout << all * 10000 <<" " << all << endl;
}
while(m > 0 && not_all_k && can_lower && i < 2 * n) {
not_all_k = not_equal_k(record, k);
// 所有工程的天数都已经为k
if(!not_all_k) break;
// 由于后面将相同项目合并了。这里不需要这个判断了
// bool same_flag = same(record);
// // 无法再将所有的工程(此时已经全部是同一个数字)全部减少一天
// cout << "enter1" << endl;
// if(same_flag && m < all) break;
// 找到天数最大的那个情况的下标?每次结束的时候会对数组排序,不用找就是第一个
// int idx = find_max(record);
// cout << "enter2" << endl;
int c1 = record[0].second;
int t1 = record[0].first;
if(record.size() > 1) {
int c2 = record[1].second;
int t2 = record[1].first;
if(m >= c1) {
int p = m / c1;
int day = t1 - t2;
if(p >= day) {
m -= day * c1;
record[0].first -= day;
record[0].second += c2;
// 注意!这里对于天数相同的项目又进行了处理
record.erase (record.begin() + 1);
}
else {
m -= p * c1;
record[0].first -= p;
}
}
else {
// 这是由于我们每次对于record排序的时候都是把减少一天需要资源最少的那个放在前面
// 我们把初始相同t的归为一类之后这个break就更好理解了!
// 可以说此时我们不怎么需要sort排序了。因为record里面不存在{5, 1}{5, 3}这些项
// 只有{5, 4}了……
// 但是我们把sort去掉之后依旧超时,此时我们发现。。我们对于最大天数的处理永远是-1,我们可以尝试每次多处理一下
break;
}
}
else {
if(m < c1) break;
int p = m / c1;
if(p >= abs(t1 - k)) {
record[0].first = k;
}
else {
m = m - p * c1;
record[0].first = record[0].first - p;
}
}
sort(record.begin(), record.end(), cmp);
i ++;
}
cout << record[0].first << endl;
return 0;
}
// 使用unordered_map保存信息
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <unordered_map>
using namespace std;
int n, m, k;
// vector<pair<int, int>> record;
unordered_map<int, int> record;
bool not_equal_k(unordered_map<int, int> a, int k) {
for(auto t = a.begin(); t != a.end(); t++) {
if(t->first != k) {
return true;
}
}
return false;
}
pair<int, int> find_max(unordered_map<int, int> a) {
pair<int, int> res = {0, 0};
int i = 0;
for(auto t = a.begin(); t != a.end(); t++) {
if(i == 0) {
res.first = t->first;
i ++;
}
else if(i == 1){
res.second = t->first;
i ++;
}
else {
break;
}
}
return res;
}
int main()
{
cin >> n >> m >> k;
int all = 0;
int t, c;
// 做法不确定是否正确并且超时了,我们在读入数据的时候把初始所需时间一样的归为一类
for (int i = 0; i < n; i ++ ) {
cin >> t >> c;
record[t] += c;
all += c;
}
bool not_all_k = true;
bool can_lower = true;
// 退出的条件是
// 1. 资源耗尽(m == 0)
// 2. 无法再将所有的工程(此时已经全部是同一个数字)全部减少一天
// 3. 所有工程的天数都已经为k
while(m > 0 && not_all_k && can_lower) {
not_all_k = not_equal_k(record, k);
// 所有工程的天数都已经为k
if(!not_all_k) break;
pair<int, int> r = find_max(record);
int c1 = record[r.first];
int t1 = r.first;
if(record.size() > 1) {
int c2 = record[r.second];
int t2 = r.second;
if(m >= c1) {
int p = m / c1;
int day = t1 - t2;
if(p >= day) {
m -= day * c1;
record[t2] += c1;
record.erase(t1);
}
else {
m -= p * c1;
record[t1 - p] += c1;
record.erase(t1);
}
}
else {
break;
}
}
else {
if(m < c1) break;
int p = m / c1;
if(p >= abs(t1 - k)) {
record[k] += c1;
record.erase(t1);
break;
}
else {
m = m - p * c1;
record[t1 - p] += c1;
record.erase(t1);
break;
}
}
}
pair<int, int> r = find_max(record);
cout << r.first << endl;
return 0;
}