《算法》第四章部分程序 part 17

▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题

● 无环图最短 / 最长路径通用程序

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.In;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.Topological;
 6 import edu.princeton.cs.algs4.DirectedEdge;
 7 import edu.princeton.cs.algs4.EdgeWeightedDigraph;
 8 import edu.princeton.cs.algs4.Stack;
 9 
10 public class class01
11 {
12     private double[] distTo;        // 起点到各顶点的距离
13     private DirectedEdge[] edgeTo;  // 引入各顶点时引入的边
14 
15     public class01(EdgeWeightedDigraph G, int s)
16     {
17         distTo = new double[G.V()];
18         edgeTo = new DirectedEdge[G.V()];
19         for (int v = 0; v < G.V(); v++)
20             distTo[v] = Double.POSITIVE_INFINITY;       // 求最长路径时改为 distTo[v] = Double.POSITIVE_INFINITY;
21         distTo[s] = 0.0;
22         Topological topological = new Topological(G);   // 堆图 G 进行拓扑排序
23         if (!topological.hasOrder())
24             throw new IllegalArgumentException("\n<Constructor> Digraph is not acyclic.\n");
25         for (int v : topological.order())               // 依照拓扑顺序松弛每条边
26         {
27             for (DirectedEdge e : G.adj(v))
28                 relax(e);
29         }
30     }
31 
32     private void relax(DirectedEdge e)
33     {
34         int v = e.from(), w = e.to();
35         if (distTo[w] > distTo[v] + e.weight())     // 加入这条边会使起点到 w 的距离变短
36         {                                           // 求最长路径时将其改为 if (distTo[w] < distTo[v] + e.weight())
37             distTo[w] = distTo[v] + e.weight();     // 确认加入该边
38             edgeTo[w] = e;
39         }
40     }
41 
42     public double distTo(int v)
43     {
44         return distTo[v];
45     }
46 
47     public boolean hasPathTo(int v)
48     {
49         return distTo[v] < Double.POSITIVE_INFINITY;// 求最长路径时将其改为 return distTo[v] < Double.POSITIVE_INFINITY;
50     }
51 
52     public Iterable<DirectedEdge> pathTo(int v)
53     {
54         if (!hasPathTo(v))
55             return null;
56         Stack<DirectedEdge> path = new Stack<DirectedEdge>();
57         for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()])
58             path.push(e);
59         return path;
60     }
61 
62     public static void main(String[] args)
63     {
64         In in = new In(args[0]);
65         int s = Integer.parseInt(args[1]);
66         EdgeWeightedDigraph G = new EdgeWeightedDigraph(in);
67         class01 sp = new class01(G, s);
68         for (int v = 0; v < G.V(); v++)
69         {
70             if (sp.hasPathTo(v))
71             {
72                 StdOut.printf("%d to %d (%.2f)  ", s, v, sp.distTo(v));
73                 for (DirectedEdge e : sp.pathTo(v))
74                     StdOut.print(e + "   ");
75                 StdOut.println();
76             }
77             else
78                 StdOut.printf("%d to %d         no path\n", s, v);
79         }
80     }
81 }

● 关键路径方法(critical path method)解决任务调度问题

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.StdIn;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.AcyclicLP;
 6 import edu.princeton.cs.algs4.DirectedEdge;
 7 import edu.princeton.cs.algs4.EdgeWeightedDigraph;
 8 
 9 public class class01
10 {
11     private class01() {}
12 
13     public static void main(String[] args)
14     {
15         int n = StdIn.readInt();                                // 任务数
16         int source = 2 * n;                                     // 0 ~ n-1 为各任务起点,n ~ 2n-1 为各任务终点
17         int sink = 2 * n + 1;                                   // 2n 为总起点,2n + 1 为总终点
18         EdgeWeightedDigraph G = new EdgeWeightedDigraph(2 * n + 2);
19         for (int i = 0; i < n; i++)
20         {
21             double duration = StdIn.readDouble();               // 第一列,任务耗时
22             G.addEdge(new DirectedEdge(source, i, 0.0));        // 总起点到任务起点的边
23             G.addEdge(new DirectedEdge(i + n, sink, 0.0));      // 任务终点到总终点的边
24             G.addEdge(new DirectedEdge(i, i + n, duration));    // 任务起点到任务终点的边
25 
26             int m = StdIn.readInt();                                // 以该任务完成为前提的其他任务数
27             for (int j = 0; j < m; j++)
28             {
29                 int precedent = StdIn.readInt();                    // 后续任务的编号
30                 G.addEdge(new DirectedEdge(n + i, precedent, 0.0)); // 添加本任务终点到后续任务起点的边
31             }
32         }
33 
34         AcyclicLP lp = new AcyclicLP(G, source);    // 生成最长路径图,尽量选权值较大的边意味着尽量把任务往前靠
35         StdOut.println(" job   start  finish");
36         StdOut.println("--------------------");
37         for (int i = 0; i < n; i++)
38             StdOut.printf("%4d %7.1f %7.1f\n", i, lp.distTo(i), lp.distTo(i + n));
39         StdOut.printf("Finish time: %7.1f\n", lp.distTo(sink));
40     }
41 }

猜你喜欢

转载自www.cnblogs.com/cuancuancuanhao/p/9836330.html