贪心,队列,运算符重载,牛客:连环爆炸

C-连环爆炸_第四届辽宁省大学生程序设计竞赛(正式赛)(重现赛)@兴安真人 (nowcoder.com)

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

星穹铁道,启动!

希儿打怪,对面是n个自爆怪。每个怪有ai​和bi​两个参数,ai​代表这个怪物的血量,bi​代表这个怪物身亡后自爆对所有单体怪物造成的伤害。


你可以选择任意怪物,进行“手动消灭”,将其血量变为0。

当一个怪物由于“手动消灭”或其他怪物的自爆,血量变为0及0以下,则该怪物被消灭,并对所有单体怪物造成bi​的伤害。

问最少“手动消灭”几个怪物能消灭所有怪物。

注意:这些怪是可以通过怪的自爆连续引爆的。

输入描述:

第一行一个正整数n,表示怪物的数量。

接下来的n行,每行两个正整数ai​和bi​。(ai​代表这个怪物的血量,bi​代表这个怪物身亡后自爆对所有单体怪物造成的伤害)

1≤n≤4000

1≤ai≤1000000000

1≤bi≤250000

输出描述:

输出一个正整数,表示能消灭所有怪物的最少使用“手动消灭”的次数。

示例1

输入

复制5 4 2 6 2 7 2 8 2 10 2

5
4 2
6 2
7 2
8 2
10 2

输出

复制2

2

示例2

输入

复制5 4 2 6 2 7 100 8 2 10 2

5
4 2
6 2
7 100
8 2
10 2

输出

复制1

1

解析:

 

1.首先,想明白杀怪的最优解。需要筛选出一定不能被炸死的怪(即所有怪爆炸伤害之和减去该怪的爆炸伤害<该怪的生命值),手动将它杀死,积累伤害值。这一步非常重要!!!!

2.剩余的都是可以被炸死的怪,可以放心地按爆炸伤害从高到低的顺序杀(注意伤害相等时先杀生命值高的),每杀一个,积累伤害值,需要找到目前伤害可以炸死的怪物,因此想到还需要一个按生命值从小到大排序的数据结构。可以知道此时怪物死到哪里了,不需要死一个怪再判断其他的怪物是否有被炸死的。

 

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>

using namespace std;
typedef long long LL;
const int N = 4e3 + 5;
int n;
struct node {
	LL a, b;
	int flg = 0;
}arr[N];

int cmp(const struct node& a, const struct node& b) {
	if (a.b == b.b)
		return a.a > b.a;
	return a.b > b.b;
}

int main() {
	cin >> n;
	LL num = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%lld%lld", &arr[i].a, &arr[i].b);
		num += arr[i].b;
	}
	sort(arr + 1, arr + 1 + n, cmp);
	LL sum = 0,cnt=0;
	int ff = 0;

	for (int i = 1; i <= n; i++) {
		if (num - arr[i].b < arr[i].a) {
			sum += arr[i].b;
			arr[i].flg = 1;
			cnt++;
		}
	}
	ff = 1;
	for (int i = 1; i <= n; i++) {
		
		//cout << cnt << endl;
		while (ff) {
			ff = 0;
			for (int j = n; j > 0; j--) {
				if (arr[j].a <= sum && arr[j].flg == 0) {
					sum += arr[j].b;
					arr[j].flg = 1;
					ff = 1;
				}
			}
		}
        if (arr[i].flg == 0) {
			arr[i].flg = 1;
			sum += arr[i].b;
			cnt++;
			ff = 1;
		}
	}
	cout << cnt << endl;
	return 0;
}

队列版:

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>

using namespace std;
typedef long long LL;
const int N = 4e3 + 5;
int n;
LL s[N][2],fg[N];
struct ss {
	int index;
	LL a, b;
	bool operator <(const ss& t)const {
		if (b == t.b)return a < t.a;
		return b < t.b;
	}
};

struct ll {
	int index;
	LL a, b;
	bool operator<(const ll& t)const {
		return a > t.a;
	}
};

priority_queue<ss>q1;
priority_queue<ll>q2;

int main() {
	cin >> n;
	int sum = 0;
	for (int i = 1; i <= n; i++) {
		scanf("%lld%lld",&s[i][0],&s[i][1]);
		sum += s[i][1];
	}
	int cnt = 0, su = 0;
	for (int i = 1; i <= n; i++) {
		fg[i] = 1;
	}
	for (int i = 1; i <= n; i++) {
		if (sum - s[i][1] < s[i][0]) {
			su += s[i][1];
			cnt++;
			fg[i] = 0;
		}
		else {
			q1.push({ i,s[i][0],s[i][1] });
			q2.push({ i,s[i][0],s[i][1] });
		}
	}
	while (!q1.empty() && !q2.empty()) {
		while (!q2.empty()&&su>=q2.top().a) {
			if(fg[q2.top().index])su += q2.top().b;
			fg[q2.top().index] = 0;
			q2.pop();
		}
		if (q2.empty())break;
		while (!q1.empty()&&fg[q1.top().index]==0) {
			q1.pop();
		}
		if (q1.empty())break;
		cnt++;
		su += q1.top().b;
		fg[q1.top().index] = 0;
		q1.pop();
	}
	cout << cnt << endl;
	return 0;
}

posted @ 2023-11-08 21:45  Landnig_on_Mars  阅读(20)  评论(0编辑  收藏  举报  来源