贪心·1671扑克牌

在这里插入图片描述

题目

一副扑克牌有 n n n张普通牌加一张特殊牌
现在 n n n种牌各有 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,,an张,还有 b b b 张特殊牌
一副牌可以由n种普通牌各一张组成,也可以由n−1种普通牌各一张再加一张特殊牌组成
输出最多能整理出的牌的副数。
在这里插入图片描述

输入

第一行给出 n n n b b b
第二行给出 a 1 , a 2 , … , a n a1,a2,…,an a1,a2,,an

输出

输出最多能整理出的牌的副数。在这里插入图片描述

数据

对于 20 20 20%的数据, 1 ≤ n ≤ 100 1≤n≤100 1n100,牌的数量小于 100 100 100
对于 40 40 40%的数据, 1 ≤ n ≤ 3000 1≤n≤3000 1n3000
对于 100 100 100%的数据, 1 ≤ n ≤ 1000000 1≤n≤1000000 1n1000000,牌的数量 ≤ 106 ≤106 106
时间限制: 1000 1000 1000 m s ms ms
内存限制: 262144 K B 262144 KB 262144KB
在这里插入图片描述

样例

input
5 5
5 5 5 5 5
output
6

在这里插入图片描述

思路

在这里插入图片描述
将扑克牌按照牌数排列(黄色区域)
很容易发现,我们只要将数量最少的牌用特殊牌代替,即可最大化地凑出一副牌。
观察问题,每一副牌最多只能用一张特殊牌,即 n n n副牌可以使用 n n n张特殊牌。
问题转换:长度为 n n n 的矩形高为 h h h,绿色格数为 a a a,求使得 a < = h a<=h a<=h h h h 的最大值
在这里插入图片描述

代码

#include<bits/stdc++.h>
using namespace std;
int n, b, ans, sum;
priority_queue< int, vector<int>, greater<int> > q;

int main() {
	scanf("%d%d", &n, &b);
	for(int i = 1, a; i <= n; i++) scanf("%d", &a), q.push(a);
	ans = sum = q.top();
	while(1) {
		for(int i = 1; i <= sum && b; i++, b--) { int d = q.top();q.pop();q.push(d+1);}
		//选择数量最少的牌,用一张特殊牌补上
		int c = q.top();//目前最高可以到达的牌数
		if(ans == c) break;//如果与上一轮得出答案相同,则最高牌数已求得
		sum = c-ans;//sum记录还可以放的绿色格格数
		ans = c;//更新答案
	}
	printf("%d\n", ans);
	return 0;
}

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值