算法学习之路——贪心

基本概念:贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

基本要素

  • 贪心选择:
    贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。
  • 最优子结构:
    当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题。
  • 无后效性:
    无后效性是指如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变化仅与此阶段的状态有关,而与过程在此阶段以前的阶段所经历过的状态无关。利用动态规划方法求解多阶段决策过程问题,过程的状态必须具备无后效性。无后效性是指如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变化仅与此阶段的状态有关,而与过程在此阶段以前的阶段所经历过的状态无关。利用动态规划方法求解多阶段决策过程问题,过程的状态必须具备无后效性。

基本思路

  • 思想:
    贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止
  • 过程:
    1.建立数学模型来描述问题;
    2.把求解的问题分成若干个子问题;
    3.对每一子问题求解,得到子问题的局部最优解;
    4.把子问题的解局部最优解合成原来解问题的一个解。

例题

  • 数列分段Section I
    题干:
    对于给定的一个长度为NNN的正整数数列AiA_iAi​,现要将其分成连续的若干段,并且每段和不超过MMM(可以等于MMM),问最少能将其分成多少段使得满足要求。
    输入格式:
    第1行包含两个正整数N,MN,MN,M,表示了数列AiA_iAi​的长度与每段和的最大值,第222行包含NNN个空格隔开的非负整数AiA_iAi​,如题目所述。
    输出格式:
    一个正整数,输出最少划分的段数。
    思路:
    对于当前元素只有两种选择 并到其他段上和单独一段。
    当前元素能找到和在一起的段就并上,找不到就自己就自己一段。
    ans一开始设置为n+1,因为还要并0号元素,没并一次少一个段。
    代码:

#include <stdio.h>
int a[100010] ;
int main()
{
int n,m,i,j,k,ans=0,sum=0;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
if(a[i]+sum>m)
{
sum=0;
ans++;
}
sum=sum+a[i];
}
if(sum)
{
ans++;
}
printf("%d",ans);
return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43597036/article/details/87430754