Problem F

题目来源:2024.6.9 宁夏理工丝绸之路邀请赛


问题描述

The British historian Alfred Crosby wrote in his book “War, Germs and the Human Experience”: “War is a competition for control of resources.”

The war between humans and the bugs ultimately stems from the bug’s greed for the resources occupied by humans. During the war, the competition is also for their respective resources. As the commander-in-chief of the Allied Forces, Professor Yu is also very concerned about the competition and possession of resources.

According to our intelligence, there are N N N resource planets in the known star regions, each with its resource amount of P i P_i Pi. Because we do not want to attract the attention of the bug, we have to control the speed of occupying planets. Each day, we can only secretly send troops to occupy one resource planet. However, because the bug also attach great importance to resource plunder, if a resource planet is not occupied by us within D i D_i Di days, the bug will occupy it. Professor Yu understands that we cannot occupy all resource planets, but he hopes that you, the commander, can help him plan the entire operation and obtain the most resources. Come on! Commander, the future of humanity is in on u!

Input
The first line of each test case contains an integer N N N ( 0 ≤ N ≤ 10000 0 ≤ N ≤10000 0N10000), which is the total number of resource planets.
The next N lines each contain two integers, P i P_i Pi and D i D_i Di ( 1 ≤ P i , D i ≤ 10000 1 ≤ P_i, D_i ≤10000 1Pi,Di10000).

Output
Output the maximum amount of resources that can be obtained under the current conditions.

Sample Input

7 
20 1
2 1
10 3
100 2
8 2
5 20
50 10 

Sample Output

185

题目翻译

英国历史学家阿尔弗雷德·克罗斯比在他的著作《战争、细菌与人类经验》中写道:“战争是一场争夺资源控制权的竞赛。”

人类与虫族之间的战争最终源于虫族对人类所占据资源的贪婪。在战争中,竞争也是为了 各自的资源。作为联军总司令的于教授也非常关注资源和占有问题。

根据我们的情报,在已知的星域中有N个资源星球,每个星球的资源量为 P i P_i Pi 。由于我们不 想引起虫族的注意,我们必须控制占领星球的速度。每天,我们只能秘密派遣军队去占领 一个资源星球。然而,因为虫族也非常重视资源的掠夺,如果在 D i D_i Di 天内我们没有占领某个资源星球,那么虫族就会占领它。于教授明白我们不能占领所有的资源星球,但他希望作 为指挥官的你能够帮助他规划整个行动并获得最多的资源。加油吧!指挥官,人类的未来 就在你手中!

输入:
每个测试用例的第一行包含一个整数 N N N 0 ≤ N ≤ 10000 0 ≤ N ≤ 10000 0N10000),它是资源星球的总数。
接下来的N行每行包含两个整数, P i P_i Pi D i D_i Di 1 ≤ P i , D i ≤ 10000 1 ≤ P_i, D_i ≤10000 1Pi,Di10000) .

输出:
在当前条件下可以获得的最大资源量。

样例输入:

7 
20 1 
2 1 
10 3 
100 2 
8 2 
5 20 
50 10 

样例输出:

185

解题

确定方法

求最大的资源总量,我们只需每次都选择最大资源的星球即可,很明显,贪心

易错陷阱

我踩过的坑
这里很容易简单化 — 每天都选择当天资源量最大的星球,循环完所有天数,得到答案。
代码:

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> Pii;

bool cmp(Pii a, Pii b) {
	if (a.second != b.second) return a.second < b.second;
	else return a.first > b.first;
}

int main() {
	int n;
	cin >> n;
	Pii p[n];
	for (int i = 0; i < n; i++) {
		cin >> p[i].first >> p[i].second;
	}
	
	sort(p, p + n, cmp);
	int ans = 0;
	int res = p[0].first;
	int day = p[0].second;
	ans += res;
	for (int i = 1; i < n; i++) {
		if (day != p[i].second) {
			res = p[i].first;
			ans += res;
			day = p[i].second;
		}
	}
	cout << ans << endl;
	return 0;
}

测试之后代码过了样例,但是隐约感觉问题没这么简单,提交,果然 WA
之后固执的认为这个思路没错,感觉是翻译有什么细节没有翻译到位,反复看题,才发现题目中的一个要点,一个关于时间的要点:
" if a resource planet is not occupied by us within D i D_i Di days, the bug will occupy it."
如果在 D i D_i Di 天内我们没有占领某个资源星球,那么虫族就会占领它。
这是解题的关键:我们不一定要卡在deadline那天占领星球
这就直接推翻了之前只关注deadline的贪心策略,这种贪心策略并不能达到全局最优
比如,对于样例:

3
1 5
2 10
2 30

最优应该选择2 102 30总资源10 + 30 = 40,而不是1 52 30总资源5 + 30 = 35
我们需要的是一种关注当下时间的最优选择来达到全局最优的目的。
这样我们可以选择使用 优先队列 来更新当前天数下的最优选择
Code思路:

  1. 按最后期限升序排序
  2. 遍历排序后的星球
    1. 如果当前队列大小小于星球的最后期限,直接将当前星球加入队列中,并更新总资源量。
    2. 如果当前队列已满(当前deadline)且当前星球的资源量大于队列中最小的资源量,用当前星球替换队列中最小的资源星球,并更新总资源量

代码 :

#include <bits/stdc++.h>

using namespace std;

struct Planet {
    int res;
    int diel;
};
// 可用pair替代Planet结构体

bool cmp(const Planet &a, const Planet &b) {
    return a.diel < b.diel;
}

int main() {
    int N;
    cin >> N;
    vector<Planet> planets(N);

    for (int i = 0; i < N; ++i) {
        cin >> planets[i].res >> planets[i].diel;
    }

    sort(planets.begin(), planets.end(), cmp);

    priority_queue<int, vector<int>, greater<int>> pq;
    int totalResources = 0;

    for (const auto &planet : planets) {
        if (pq.size() < planet.diel) {
            pq.push(planet.res);
            totalResources += planet.res;
        } 
        else if (!pq.empty() && pq.top() < planet.res) {
            totalResources += planet.res - pq.top();
            pq.pop();
            pq.push(planet.res);
        }
    }

    cout << totalResources << endl;

    return 0;
}
/* pair

// 使用'&'取值可以避免拷贝提高效率
bool cmp(pair<int, int> &a, pair<int, int> &b) {
	return a.second < b.second;
}

int main() {
    int N;
    cin >> N;
    vector<pair<int, int>> planets(N);

    for (int i = 0; i < N; ++i) {
        cin >> planets[i].first >> planets[i].second;
    }

    sort(planets.begin(), planets.end(), cmp);

    priority_queue<int, vector<int>, greater<int>> pq;
    int ans = 0;

    for (const auto &planet : planets) {
        if (pq.size() < planet.second) {
            pq.push(planet.first);
            ans += planet.first;
        } else if (!pq.empty() && pq.top() < planet.first) {
            ans += planet.first - pq.top();
            pq.pop();
            pq.push(planet.first);
        }
    }

    cout << ans << endl;

    return 0;
}
*/

没了

  • 14
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值