信息学奥赛一本通 贪心算法
【题目描述】
一副扑克牌有n张普通牌加一张特殊牌
现在n种牌各有a1 , a2 , … , an张,还有 b bb 张特殊牌
一副牌可以由n种普通牌各一张组成,也可以由n−1种普通牌各一张再加一张特殊牌组成
输出最多能整理出的牌的副数。
【输入】
第一行给出n和b。
第二行给出a1,a2,…,an。
【输出】
输出最多能整理出的牌的副数。
【数据】
对于20%的数据,1≤n≤100,牌的数量小于100。
对于40%的数据,1≤n≤3000。
对于100%的数据,1≤n≤1000000,牌的数量 ≤。
时间限制: 1000ms
内存限制: 262144KB
【输入样例】
5 5
5 5 5 5 5
【输出样例】
6
【分析】
题目描述不是太好理解,现在对样例数据进行一个解读。5种牌分别各有5张,就以1、2、3、4、5来表示,即1有5张,2有5张……那么答案的6副牌是什么样的呢,我用表格来表示,每一行表示一副牌,其中T表示特殊牌。
T | 2 | 3 | 4 | 5 |
1 | T | 3 | 4 | 5 |
1 | 2 | T | 4 | 5 |
1 | 2 | 3 | T | 5 |
1 | 2 | 3 | 4 | T |
1 | 2 | 3 | 4 | 5 |
补充一个样例:
5 5
5 1 2 3 4
答案:3
也是五种牌,每种牌的数量不相同了,需要先对牌的数量进行一个排序,表格中上面三行对应答案的3副牌。
T | 2 | 3 | 4 | 5 |
T | 2 | 3 | 4 | 5 |
1 | T | 3 | 4 | 5 |
4 | 5 | |||
5 |
题目适用于贪心来解题,调整几种牌中数量最小的那个。补充样例中,不使用特殊牌,只能凑出1副牌(1,2,3,4,5),将特殊牌补充到1里,可以凑出2副牌(T,2,3,4,5 / 1,2,3,4,5),再将特殊牌补充到1、2各一个,可以凑出3副牌,如上面表格所示。那么可以继续添加特殊牌吗?再添加一个T到1、2、3中一列,还有两个空无法填充,即用了4个特殊牌也只能凑出3副牌。
补充特殊牌退出条件有两个:
1、使用特殊牌的数量大于能凑出的牌数,即大于队列中最小的那个数,如补充例子里展示的那样
2、特殊牌用完了
#include<bits/stdc++.h>
using namespace std;
int n,b;
//优先队列
priority_queue <int, vector<int>,greater<int>> q;
int ans;
int main() {
cin>>n>>b;
for(int i=1;i<=n;i++){//优先队列保存n张牌
int a;
cin>>a;
q.push(a);
}
ans=q.top();//记录最初可以凑出的牌数
for(int i=1;i<=b;i++){//将特殊牌补充到队列里
int t = q.top();
q.pop();
t++;//加到最少的那种牌里
q.push(t);//补充后放回队列
ans=q.top();//当前最少的牌数,即当前可凑出的牌数
if (i>ans){//如果使用的特殊牌超过了整副牌数量,表示无法再凑出更多的牌数了
break;
}
}
cout<<ans;//输出答案
//cout << q.top()
return 0;
}