本质特征(区分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;