poj 1017 贪心算法

贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题、最小生成树问题、背包问题,赛程安排问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。

贪心算法的基本要素

对于一个具体的问题,怎么知道是否可用贪心算法解此问题,以及能否得到问题的最优解呢?这个问题很难给予肯定的回答。

但是,从许多可以用贪心算法求解的问题中看到这类问题一般具有2个重要的性质:贪心选择性质和最优子结构性质。

1、贪心选择性质

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。 

对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

2、最优子结构性质

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 

3、贪心算法与动态规划算法的差异

贪心算法和动态规划算法都要求问题具有最优子结构性质,这是2类算法的一个共同点。但是,对于具有最优子结构的问题应该选用贪心算法还是动态规划算法求解?是否能用动态规划算法求解的问题也能用贪心算法求解?下面研究2个经典的组合优化问题,并以此说明贪心算法与动态规划算法的主要差别。

题意:有底面积为1*1, 2*2, 3*3, 4*4, 5*5, 6*6的货物,题目给出了六种货物的数量,问最少用多少个6*6 的包裹能装下所有的货物

思路:贪心算法,从大的开始放,然后用小的嵌进去。循环后是不行的,只能一一的分析。

#include<stdio.h>
#include<string.h>  
int
abs
(
int
x){
return
x<0?0:x;}
int
main()
{
    
int
a[10];
    
while
(1){
        
int
sum=0,h,m;
        
for
(
int
i=1;i<=6;i++){
            
scanf
(
"%d"
,&a[i]);
            
sum+=a[i];
        
}
        
if
(sum==0)
break
;
        
sum=a[6];
        
sum+=a[5];a[1]=
abs
(a[1]-11*a[5]);
        
sum+=a[4];h=20*a[4]-4*a[2];
        
if
(h>0)a[1]=
abs
(a[1]-h);
        
a[2]=
abs
(a[2]-5*a[4]);
        
sum+=a[3]/4;
        
h=-1,m=4-a[3]%4;
        
if
(m<4)
            
sum++;
        
if
(m==1)
            
h=9-4*(a[2]>0?1:0),a[2]=
abs
(a[2]-1);
        
else
if
(m==2)
            
h=18-4*(a[2]>=3?3:a[2]),a[2]=a[2]>=3?a[2]-3:0;
        
else
if
(m==3)
            
h=27-4*(a[2]>=5?5:a[2]),a[2]=a[2]>=5?a[2]-5:0;
        
if
(h>0)a[1]=
abs
(a[1]-h);
        
m=a[1]+4*a[2];
        
if
(m%36)
            
sum+=m/36+1;
        
else
            
sum+=m/36;
        
printf
(
"%d\n"
,sum);
    
}
}

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/zhanghaipeng1989/article/details/6841024
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞