算法学习——贪心法

贪心算法是一种解决问题的策略,它通过每次选择局部最优解来逼近全局最优解。在本文中,我们探讨了贪心算法的本质特征,如与DP和分治的区别,以及它的快速但不保证最优解的特点。内容涵盖了贪心算法的设计关键,以及如何在程序中实现。具体实例包括Dijkstra算法用于求解有向无负权图的单源最短路径,以及两种最小生成树的构造方法:Kruskal和Prim算法。
摘要由CSDN通过智能技术生成

本质特征(区分dp、分治)

只选择一个子问题

 

特点

1.快

2.不能保证获得最优解,可以作为近似解,一般,在特殊情况下可保证最优解。

3.适合于组合优化问题

 

设计关键

贪心选择策略(分解方案)

 

程序写法

S = s0,C = c0; // 部分解S,候选集C

while(!complete(s)){
    x = select(c); // 贪心选择主体    
    if(flexible(x)){ // 可行函数,判断贪心选择结果是否满足约束条件
       S = S ∪ {x} // 解扩展
         }
    C = C - {x}; //C中参数重新计算以及候选集调整
    }

 

例子

1、Dijkstra算法——求单源最短路径(有向无负权图)

注意:实现时dist[] 的初始值若源点和i之间无边,则一定要为无穷大(例如XX.MAX_VALUE等),若为0,则后面会更新不了,导致结果出错

实现一:邻接矩阵实现

public class Greedy {


    float[][] arr; // 表示边的权,若没有连接的边则用最大值表示
    boolean[] s; // 表示已找到最短路径的点集合
    int[] pre; // 最短路径中某个点对应的前驱节点
    float[] dist; // 从源到所有其他顶点的最短路径
    int m; // 图中边的条数
    int n; // 图中的点的个数
    int v; // 源


    public static void main(String[] args){

        new Greedy().run();
    }

    public void run(){

        Scanner scanner = new Scanner(System.in);
        v = 0;
        n = scanner.nextInt();
        m = scanner.nextInt();
        arr = new float[n][n];
        s = new boolean[n];
        pre = new int[n];
        dist = new float[n];
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                arr[i][j] = Float.MAX_VALUE;
            }
        }
        for(int i = 0;i < m;i++){
            int a = scanner.nextInt()-1;
            int b = scanner.nextInt()-1;
            float c = scanner.nextFloat();
            arr[a][b] = c;
//            arr[b][a] = c; 若为无向图则加上
        }
        dijkstra();
        System.out.println(Arrays.toString(dist));
    }



    public void dijkstra(){

        // 初始化
        for(int i = 0;i < n;i++){
          dist[i] = arr[v][i];
          if(dist[i] == Float.MAX_VALUE){
              pre[i] = -1;
          }else {
              pre[i] = v;
          }
        }

        dist[v] = 0;
        s[v] = true;


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值