贪心算法(Greedy Algorithm) 概述:贪心算法是一种在求解最优化问题时采取的一种常用算法策略。贪心算法的基本思想是,每次选择当前情况下的局部最优解,并相信这个局部最优解能够导致全局最优解。贪心算法通过迭代的方式一步步地构建最优解,并不进行回溯。
贪心算法的一般步骤:1. 将问题分解成多个子问题;
2. 对每个子问题,确定一个最优解;
3. 对每个子问题的最优解进行合并,得到原问题的最优解。
贪心算法的正确性需要满足两个条件:1.最优子结构:问题的最优解能够由子问题的最优解组合而成。
2. 贪心选择性:通过局部最优选择能够得到全局最优解。
贪心算法适用的问题一般具有以下特点:1. 子问题的最优解能够推导出原问题的最优解;
2. 子问题的最优解构成原问题的最优解时,原问题的最优解也能由它推导出。
贪心算法的优点是简单、高效,时间复杂度通常较低。然而,贪心算法并不适用于所有问题,有些问题需要使用其他更复杂的算法来求解。在使用贪心算法时,需要仔细分析问题的特点并证明贪心策略的正确性。
由于贪心是一种思想,没有具体的算法模板,而且贪心一般不会单独作为一种算法出现在题目中,一般会跟其他算法结合在一起出现。例如:动态规划、递归、高级数据结构等。在此基础上保证每一步时最优解的情况下就可以得到最优的答案。下面我们将以例题的形式让大家来了解这种思想。
例题一: AcWing 3769. 移动石子题目:一共有 n 个箱子排成一排,从左到右依次编号为 1∼n。
其中,第 i 号箱子中放有 ai个石子。
现在,你可以进行最多 d 次操作。
每次操作可以将一个石子从一个箱子移动至另一个与其相邻的箱子里。
我们希望通过合理操作使得 1 号箱子内的石子数量尽可能大。
请问,这个最大可能值是多少?
输入格式第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含两个整数 n和 d。
第二行包含 n 个整数 a1,a2,…,an。
输出格式每组数据输出一行结果,表示答案。
数据范围1≤T≤100,
1≤n,d≤100,
0≤ai≤100.
输入样例:代码语言:javascript复制3
4 5
1 0 3 2
2 2
100 1
1 8
0输出样例:代码语言:javascript复制3
101
0解题思路:这个题很明显贪心思想,要让第一个箱子尽可能多的石子,在操作次数的限制下,我们最优解,要从第二个箱子开始贪心,第二个、第三个...,这样可以使操作次数尽可能的少。
AC代码:代码语言:javascript复制#include
using namespace std;
const int N=105;
int t,n,d;
int a[N];
int main(){
cin>>t;
while(t--){
cin>>n>>d;
for(int i=1;i<=n;i++)cin>>a[i];
int k=2;
while(d){
if(k>n)break;
if(d>=a[k]*(k-1)){
a[1]+=a[k];
d-=a[k]*(k-1);
}else{
a[1]+=d/(k-1);
d=0;
}
k++;
}