一、贪心算法的根本思想
例如:求生存某种商品的所花费的时间最少;
最直接方法:枚举;
高效一点方法:逐步的局部最优实现全局最优
二、贪心算法的基本要素:
贪心选择性质和最优子结构性质
贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
与动态规划主要区别是,动态规划是自底向上解决问题,贪心算法是自顶而下解决问题。
动态规划中父问题与子问题是有相关依赖性,父问题是以子问题为条件,而贪心算法父子无相关依赖性。
最优子结构性质,当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。不能采用分治法解决的问题,是理论上是不能使用贪心算法的,而且,必须拥有最优子结构性质,才能保证贪心算法返回最优解。
可绝对贪心:具有贪婪选择性质,最优子结构性质
相对贪心问题:求近似解,不具备全部性质
三、关于贪心算法的一些PPT例题:
1.删数求最小问题
输入一个高精度整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数,寻找其剩下的新数最下。
#include<bits/stdc++.h>
using namespace std;
char a[250];//使用字符数组存放数
int main(){
int s,n;
int falg=1;//用于以后检测0是否是第一位;
scanf("%s %d",a,&s);
n=strlen(a);
//cout<<n;
//这一步循环用于删除数:删除比前一位大的数字
while(s!=0){
int i=0;
while(a[i]<=a[i+1]){
i++;
}
while(i<n-1){
a[i]=a[i+1];
i++;
}
n--;
s--;
}
//用于输出
for(int i=0;i<n;i++){
//检测第一位是否是0
if(a[i]=='0'&&falg==1&&i<n-1){
continue;
}
else{
printf("%c",a[i]);
falg=0;
}
}
return 0;
}
2.数列极差问题
写下n个数,每一次擦去两个数a 和 b ,然后再数列中写上a*b-1,直至剩下一个数字,在所有这种情况中,最大的记作max,最小的记作min,求max-min.
#include<bits/stdc++.h>
using namespace std;
int a[1000];//创建两个数组,一个用于计算max_num,一个用于计算min_num
int b[1000];
int max_num;
int min_num;
//降序排列
bool cmp(int a,int b){
return a>b;
}
int main(){
int i,n;
cin>>n;//数长
//输入数值
for(i=0;i<n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(a,a+n);//升序排序
for(i=1;i<n;i++){
a[i]=a[i]*a[i-1]+1;
sort(a+i,a+n);//每计算一次再次排序,保证从小到大相乘
}
max_num=a[n-1];
sort(b,b+n,cmp);//降序排序
for(i=1;i<n;i++){
b[i]=b[i-1]*b[i]+1;
}
min_num=b[n-1];
int result=max_num-min_num;//得出结果
return result;
}
3.埃及分数
把一个真分数表示为埃及分数之和的形式。所谓的埃及分数,是指分子为1的分数。
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b,c;//a是分子,b是分母,c用于计算
cin>>a>>b;
if(a==1||b%a==0){//当分子为1或者可约分的分数时直接输出
cout<<"1/"<<b/a;
}
while(a!=1){
c=b/a+1;//a/b一定大于1/c
cout<<"1/"<<c;
a=a*c-b;//a/b-1/c计算,分子变为a*c-b,分母变为b*c
b=b*c;
cout<<"+";
if(a==1||b%a==0){//继续判断
cout<<"1/"<<b/a;
a=1;
}
}
return 0;
}
4.取数游戏(贪心算)
将一组数字进行编号,查看是奇数编号的数字和大还是偶数编号的数字和大,加入是奇数大,我们就选编号是奇数的数字,那么另一个就只能选择偶数字,这样选完以后,我们一定是数字和大的那一方。
代码无。
5.背包问题(非0-1背包,可局部选装载)
计算性价比,首选性价比高的那一方。
6.构建哈夫曼树