【Daily Code】CSP垦田计划

自己写了两个版本。。。但是总是超时,这种题目选好合适的数据结构很重要

// 使用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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值