最大的卡牌价值(Lanqiao OJ 3250)

文章讨论了利用贪心策略和优先队列实现的算法,解决给定卡牌问题,计算在有限次翻转后卡牌总价值的最大值。
摘要由CSDN通过智能技术生成

#贪心 #优先队列


问题描述:

给定n 副卡牌,每张卡牌具有正反面,正面朝上数字为 ai,背面朝上数字为 bi。一副卡牌的价值为正面朝上数字之和。一开始所有卡牌都是正面朝上的。小蓝是蓝桥学院最优秀的魔法师,他知道所有卡牌的背面数字 bi,他最多可以进行  k 次操作,每次可以将一副卡牌翻转,将正面朝上的数字变为背面朝上的数字,或将背面朝上的数字变为正面朝上的数字。请问,小蓝最多可以使卡牌的价值之和为多少?


输入格式:

第一行输入两个整数 n 和 k ,表示卡牌的数量和小蓝可以操作的次数。

第二行输入 n 个整数 ai ,表示所有卡牌正面的数字。

第三行输入 n 个整数 bi ,表示所有卡牌反面的数字。

数据范围保证:

1 ≤ n ≤ 1×10^5 ,

1 ≤ ai,bi ,k ≤ 10^9


输出格式:

输出一个整数,表示可以得到的卡牌的最大价值和。


样例输入:

3 1
1 2 3
3 2 1

样例输出:

8

样例说明:

将第一张卡牌翻转,此时卡牌的总和为  3 + 2 + 3 = 8 。


题解:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll n = 1e5 + 9;
ll a[n], b[n];
priority_queue<ll, vector<ll>, less<ll>>pq;

int main() {
	ll n, k;
	ll ans = 0;
	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		ans += a[i];
	}
	for (int i = 1; i <= n; i++) {
		cin >> b[i];
	}
	for (int i = 1; i <= n; i++) {
		pq.push(b[i] - a[i]);
	}
	while (k-- && !pq.empty()) {
		if (pq.top() > 0)
			ans += pq.top();
		pq.pop();
	}
	cout << ans << endl;

	return 0;
}

总结:

首先定义两个数组,用来存放卡牌的正面和卡牌的反面。

定义一个优先队列用于记录卡牌正反面的差值,less< ll >,表示采用大顶堆的排序顺序,即队列由大到小进行排列。再将差值加到 ans 中,ans 即为最大的卡牌价值 。

本题也可采用小顶堆的方式,即less< ll >。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值