基本原理:每一步都选择局部最优解,而尽量不考虑对后续的影响,最终达到全局最优解。
局限性:贪心算法不能保证获得全局最优解,但在某些问题上具有高效性。
特征:贪心选择性质,最优子结构性质,(操作次数一定,不同操作产生贡献相同,每次选择代价最小的)贪心往往和排序、优先队列等一起出现。
经验:
蓝桥 知识点:贪心
小蓝是机甲战队的队长,他手下共有 n名队员,每名队员都有一个战斗力值 wi。现在他需要将这 n名队友分成两组 a 和 b,分组必须满足以下条件:
战斗力差距的计算公式为 ∣max(a)−min(b)∣,其中 max(a) 表示 a 组中战斗力最大的,min(b)表示 b组中战斗力最小的。
请你计算出可以得到的最小战斗力差距。
第一行一个整数 n,表示队员个数。
第二行 n 个整数 w1,w2,w3…wn,分别表示每名队友的战斗力值。
数据范围保证:2≤n≤10^5,1≤wi≤10^9。
输出一个整数,表示可以得到的最小战斗力差距。
3
1 2 3
1
样例中,当 a=[1,3],b=[2],此时战斗力差距为 1,无法得到比 1 更小的安排方式。
#include
using namespace std;
using ll=long long;
const int N=1e5+9;
int a[N];
int main(){
int n; cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
sort(a+1,a+n+1);
int ans=a[2]-a[1];
for(int i=3;i<=n;++i){
ans=min(a[i]-a[i-1],ans);
}
cout<
蓝桥 知识点:贪心
在很久很久以前,有 n个部落居住在平原上,依次编号为 1到 n。第 i个部落的人数为 ti。
有一年发生了灾荒。年轻的政治家小蓝想要说服所有部落一同应对灾荒,他能通过谈判来说服部落进行联合。
每次谈判,小蓝只能邀请两个部落参加,花费的金币数量为两个部落的人数之和,谈判的效果是两个部落联合成一个部落(人数为原来两个部落的人数之和)。
输入的第一行包含一个整数 n,表示部落的数量。
第二行包含 n个正整数,依次表示每个部落的人数。
其中,1≤n≤1000,1≤ti≤10^4。
输出一个整数,表示最小花费。
输入
4
9 1 3 5
输出
31
#include
using namespace std;
using ll=long long;
const int N=1e5+9;
priority_queue,greater> pq; //注意优先队列的参数 默认降序排列!!!
int main(){
int n; cin>>n;
for(int i=1;i<=n;++i) {
ll x; cin>>x;
pq.push(x);
}
ll ans=0;
while(pq.size()>=2){
ll x=pq.top(); pq.pop();
ll y=pq.top(); pq.pop();
pq.push(x+y);
ans+=x+y;
}
cout<
蓝桥 知识点:贪心
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。
你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
第 1 行包括一个整数 w (80≤w≤200),为每组纪念品价格之和的上限。
第 2 行为一个整数 n (1≤n≤30000),表示购来的纪念品的总件数。
第3 ~ n+2行每行包含一个正整数 pi (5≤pi≤w),表示所对应纪念品的价格。
输出一行,包含一个整数,即最少的分组数目。
输入
100
9
90
20
20
30
50
60
70
80
90
输出
6
#include
using namespace std;
using ll=long long;
const int N=1e5+9;
int a[N];
int main(){
int m; cin>>m;
int n; cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
sort(a+1,a+1+n); //先排序
int l=1,r=n,ans=0;
while(l<=r){
ans++;
if(l==r) break;
if(a[l]+a[r]<=m){ //只能装两个 看最大与最小能否装在一起
l++;r--;
}else{
r--;
}
}
cout<
蓝桥 知识点:贪心
最近暑期特训算法班的同学们表现出色,他们的老师肖恩决定给他们分发糖果。肖恩购买了 n 个不同种类的糖果,用小写的阿拉伯字母表示。每个糖果必须分发给一个同学,并且每个同学至少要分到一个糖果。同学们的开心程度定义为他们所分到的糖果组成的字符串 s[i]的字典序。肖恩希望同学们的开心程度相差尽量小,因此他要找到一种方案,使得所有糖果组成的字符串中字典序最大的字符串尽可能小。请输出能够实现字典序最小可能的 max(s[1],s[2],s[3],…,s[x])。
第一行输入两个整数 n 和 x ,分别表示有 n个糖果 x个同学。
第二行输入一个长度为 n的字符串 S , S[i]表示第 i个糖果的种类。
数据保证 1≤n≤10^6,1≤x≤n,S[i]∈[′a′,′z′] 。
输出一个字符串,为所有糖果组成的字符串中字典序最大的字符串最小的可能值。
6 2
caabdc
abccd
一个最优分配方案是一个同学拿到 abccd ,一个同学拿到 a 。
#include
using namespace std;
using ll=long long;
const int N=1e6+9;
char s[N];
int main(){
int n,x; cin>>n>>x;
cin>>s+1;
sort(s+1,s+1+n);
if(s[1]==s[n]){ //8 3 aaaaaaaa aa aaa aaa->字典序最大的最小的可能情况
for(int i=1;i<=ceil((double)n/x);++i) cout<字典序最大的最小的可能情况
for(int i=x;i<=n;++i) cout<字典序最大的最小的可能情况
cout<