贪心算法(一)

贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心算法其实是一种优化后的动态规划。
 
典型例题
1.过桥
有 n 个人希望在晚上通过一座桥。在任何时刻,最多只能有两个人在桥上,而且必须要带着电筒才能过桥。一共只有一个手电筒,所以必须安排某种顺序,使得手电筒可以被带回去让更多的人过桥(手电筒必须由人带回,不可以从对岸扔过去)。每个人都有不同的过桥时间,两个人一起过桥所花的时间等于其中较慢的一个。你的任务是要找出能在最短时间内使所有人都过桥的方案。
分析:
由于模拟此题过于复杂,考虑将过河分为几个小的单元来寻找规律。
为了得到最优解,单纯运送手电筒的工作一定会交由过桥时间最短的两人来完成。于是出现了两种情况:
  1. 最快的人将手电筒运回来,最快的和最慢的过去,最快的再回来,最快的和次慢的过去。
  2. 最快的人将手电筒运回来,最慢的和次慢的过去,次快的把手电筒运回来,最快的和次快的过去。
经由推理得到公式:t[i]+t[i-1]= min(a[1]*2 + a[i-1] + a[n],a[1] + a[2]*2 + a[i])
由于a[1]+a[i-1] 与 a[2] 的大小关系是不确定的,所以只有通过对实际情况比较来判断。
while(n > 3) 
{
    s += min(a[1]*2 + a[n-1] + a[n],a[1] + a[2]*2 + a[n]);
    n -= 2;            
}
if(n == 1) s += a[1];
else if(n == 2) s += a[2];
else s += a[1]+a[2]+a[3];
printf("%d",s); 
 
2.某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。输入导弹依次飞来的高度(雷达给出的高度数据是le 5000050000的正整数),计算如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
分析:
所有系统拦截的导弹呈单调递减序列 ->由此说明,若当前没有可以拦截该导弹的系统,则必须增加一个系统。若有,则是当前拦截高度大于等于导弹高度的系统拦截该导弹为最优解。由反证法即可证明。
while(cin>>x)
{
    if(top==0)
    {
        q[++top]=x;
        ans++;
    }
    else if(q[top]<x)
    {
        ans++;
        q[++top]=x;
    }
    else 
    {
        for(int i=1;i<=top;i++)
            if(q[i]>=x)
            {
                q[i]=x;
                break;
            }
    }
}
原文地址:https://www.cnblogs.com/Cindy-Chan/p/11033162.html