以前做了个什么网络计划的算法,昨天拿来一看,好像还有问题,早上过来,弄了下,加了注释,和调试信息输出的功能,方便理解,我调试了下,没发现什么问题,如果大家发现的话,请告诉我,谢谢。
由于程序是没人那么聪明的,只有遍历了。
首先,两点之间加上中间那条线,用个类保存,类说明了这段路程的三个基本属性:起始点、结束点、需要时间,剩下的五个附加属性是遍历的时候要用到的:skip、hasFrontNode、eNodeIsBranchEndNode、sNodeIsBranchEndNode、sNodeIsBranchBeginNode,skip说明这段是否已经走过, hasFrontNode说明是否还有前驱节点,eNodeIsBranchEndNode说明这段路程的尾节点是否有多个前驱,sNodeIsBranchBeginNode是头节点是否有多个后继。
首先,将所有路程信息用个数组保存起来。addProcessInfo(int sNode,int eNode,int lTime)是将一段路程的基本信息保存,setup()加入多段具体的路程信息,然后setNodeTag() 为每段路程信息的附加属性赋值。
最主要的就在searchProcess(int sNode,int eNode)函数了,这是求任意两点间的,理论上来说,顺着找和倒着找是一样的,但是为了这个项目,我用的是倒着找的,因为要的是开始点到某个点的,顺着找的话,会走好多冤枉路,倒着的话,由于起点就一个,一般可以直接找到,而不会走过去了。
下面说说这段函数的原理:
找路径,好比人走路,找最优路径,需要走遍所有的路才能知道。一开始,看看所处的位置可以有几条路,都记下来,然后,每次挑一条可以走的路,走下去,走到走不动的地方,往回走,直到回到上个叉路口,如果回到起点,只能说明,没路了.....否则,就从后退到的那个路口继续那样的找路过程。走到终点后,记下这条路,然后,回到上个叉路口,继续走,又到终点,比比原来记下来的路,看哪条好,去掉不好的。一直就这么找,直到你走完所有的可能,才可能得到最优的解。
找一个点到另一个点的最优路径,对于程序来说,问题就在于怎么保存走过的路,应该怎么保存,保存的是什么内容。由于我是倒着找的,所以在这段代码中,我保存的是new ProcessInfo(sNode, eNode,pInfo.lastingTime),实际上是不存在这样的路径的,只是为了方便回溯保存的,然后,递归找开始节点到当前路径的开始节点间的路径。
下面我把代码贴出来,再附加二个调试信息,方便大家理解,关于那个网络图的定义可以在setup()函数中修改。
首先是保存路径信息的类(ProcessInfo.java):
分支路径栈加入:7-->8
分支路径栈加入:8-->8
分支路径栈弹出:8-->8
头尾节点一样,丢弃!
分支路径栈弹出:7-->8
回溯栈加入:2-->8,说明找过2-->8
查找:2-->7
分支路径栈加入:2-->7
分支路径栈加入:3-->7
分支路径栈加入:5-->7
分支路径栈加入:6-->7
分支路径栈弹出:6-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->6
分支路径栈加入:4-->6
分支路径栈弹出:4-->6
回溯栈加入:2-->6,说明找过2-->6
查找:2-->4
分支路径栈加入:2-->4
分支路径栈弹出:2-->4
--------到达起点:2-->4--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->6
回溯栈内容进入临时结果栈:2-->4
========找到更优解!========
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->4
找到目标,回溯栈回退到:2-->6
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支已被找遍
分支路径栈弹出:5-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->5
分支路径栈加入:2-->5
分支路径栈加入:4-->5
分支路径栈弹出:4-->5
回溯栈加入:2-->5,说明找过2-->5
查找:2-->4
分支路径栈加入:2-->4
分支路径栈弹出:2-->4
--------到达起点:2-->4--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->5
回溯栈内容进入临时结果栈:2-->4
--------回退到节点:5--------
找到目标,回溯栈回退到:2-->4
找到目标,回溯栈回退到:2-->5
分支已被找遍
分支路径栈弹出:2-->5
--------到达起点:2-->5--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->5
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->5
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支路径栈弹出:3-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->3
分支路径栈加入:2-->3
分支路径栈弹出:2-->3
--------到达起点:2-->3--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->3
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->3
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支路径栈弹出:2-->7
--------到达起点:2-->7--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
分支已被找遍
分支已被找遍
-->4-->6-->7-->8 下面来个找3到7的:
由于程序是没人那么聪明的,只有遍历了。
首先,两点之间加上中间那条线,用个类保存,类说明了这段路程的三个基本属性:起始点、结束点、需要时间,剩下的五个附加属性是遍历的时候要用到的:skip、hasFrontNode、eNodeIsBranchEndNode、sNodeIsBranchEndNode、sNodeIsBranchBeginNode,skip说明这段是否已经走过, hasFrontNode说明是否还有前驱节点,eNodeIsBranchEndNode说明这段路程的尾节点是否有多个前驱,sNodeIsBranchBeginNode是头节点是否有多个后继。
首先,将所有路程信息用个数组保存起来。addProcessInfo(int sNode,int eNode,int lTime)是将一段路程的基本信息保存,setup()加入多段具体的路程信息,然后setNodeTag() 为每段路程信息的附加属性赋值。
最主要的就在searchProcess(int sNode,int eNode)函数了,这是求任意两点间的,理论上来说,顺着找和倒着找是一样的,但是为了这个项目,我用的是倒着找的,因为要的是开始点到某个点的,顺着找的话,会走好多冤枉路,倒着的话,由于起点就一个,一般可以直接找到,而不会走过去了。
下面说说这段函数的原理:
找路径,好比人走路,找最优路径,需要走遍所有的路才能知道。一开始,看看所处的位置可以有几条路,都记下来,然后,每次挑一条可以走的路,走下去,走到走不动的地方,往回走,直到回到上个叉路口,如果回到起点,只能说明,没路了.....否则,就从后退到的那个路口继续那样的找路过程。走到终点后,记下这条路,然后,回到上个叉路口,继续走,又到终点,比比原来记下来的路,看哪条好,去掉不好的。一直就这么找,直到你走完所有的可能,才可能得到最优的解。
找一个点到另一个点的最优路径,对于程序来说,问题就在于怎么保存走过的路,应该怎么保存,保存的是什么内容。由于我是倒着找的,所以在这段代码中,我保存的是new ProcessInfo(sNode, eNode,pInfo.lastingTime),实际上是不存在这样的路径的,只是为了方便回溯保存的,然后,递归找开始节点到当前路径的开始节点间的路径。
下面我把代码贴出来,再附加二个调试信息,方便大家理解,关于那个网络图的定义可以在setup()函数中修改。
首先是保存路径信息的类(ProcessInfo.java):
1
/**
2
* @author zxub Created on 2005-5-21 10:36:29
3
*
4
*/
5
public class ProcessInfo {
6
7
//基本信息:startNode,endNode,lastingTime
8
protected int startNode; //开始节点
9
protected int endNode; //终止节点
10
protected int lastingTime; //路径持续时间
11
//下面是附加信息,遍历的时候用到
12
protected boolean skip; //判断该路径是否已经走过
13
protected boolean hasFrontNode; //路径是否有前驱节点
14
protected boolean eNodeIsBranchEndNode; //路径终止节点是否有多个前驱
15
protected boolean sNodeIsBranchBeginNode; //路径开始节点是否有多个后继
16
17
/**
18
* 保存任意两点间路径信息
19
* @param sNode 开始节点
20
* @param eNode 终止节点
21
* @param lTime 持续时间
22
*/
23
public ProcessInfo(int sNode,int eNode,int lTime)
24
{
25
this.startNode=sNode;
26
this.endNode=eNode;
27
this.lastingTime=lTime;
28
//由于是刚开始保存,下面的几个信息不能确立,所以都是false
29
this.skip=false;
30
this.hasFrontNode=false;
31
this.eNodeIsBranchEndNode=false;
32
this.sNodeIsBranchBeginNode=false;
33
}
34
}
然后,是主要的处理类(ProcessOpera.java):
/**2
* @author zxub Created on 2005-5-21 10:36:293
* 4
*/5
public class ProcessInfo {6
7
//基本信息:startNode,endNode,lastingTime8
protected int startNode; //开始节点9
protected int endNode; //终止节点10
protected int lastingTime; //路径持续时间11
//下面是附加信息,遍历的时候用到 12
protected boolean skip; //判断该路径是否已经走过13
protected boolean hasFrontNode; //路径是否有前驱节点14
protected boolean eNodeIsBranchEndNode; //路径终止节点是否有多个前驱15
protected boolean sNodeIsBranchBeginNode; //路径开始节点是否有多个后继 16

17
/**18
* 保存任意两点间路径信息19
* @param sNode 开始节点20
* @param eNode 终止节点21
* @param lTime 持续时间22
*/23
public ProcessInfo(int sNode,int eNode,int lTime)24
{25
this.startNode=sNode;26
this.endNode=eNode;27
this.lastingTime=lTime;28
//由于是刚开始保存,下面的几个信息不能确立,所以都是false29
this.skip=false;30
this.hasFrontNode=false;31
this.eNodeIsBranchEndNode=false; 32
this.sNodeIsBranchBeginNode=false;33
}34
} 1
import java.util.Stack;
2
3
/**
4
* @author zxub Created on 2005-5-22 10:19:51
5
*/
6
public class ProcessOpera
7
{
8
9
final int MAX = 100;
10
// 保存路径信息的数组
11
ProcessInfo process[] = new ProcessInfo[MAX];
12
// 保存路径数目
13
int numProcess = 0;
14
// 分支路径栈
15
Stack branchProcessStack = new Stack();
16
// 用于搜索回退的栈
17
Stack backTrackStack = new Stack();
18
// 保存最后结果的栈
19
Stack resultStack = new Stack();
20
// 最长持续时间
21
int maxLastingTime = 0;
22
23
/**
24
* 测试用
25
*
26
* @param args
27
*/
28
public static void main(String[] args)
29
{
30
31
ProcessOpera processOpera = new ProcessOpera();
32
processOpera.setup();
33
processOpera.setNodeTag();
34
// for (int i = 0; i < processOpera.numProcess; i++)
35
// {
36
// System.out.print(processOpera
37
// .getItemEarliestBeginTime(processOpera.process[i].startNode)
38
// + " ");
39
// System.out.print(processOpera.getProcessEarliestEndTime(
40
// processOpera.process[i].startNode,
41
// processOpera.process[i].endNode)
42
// + " ");
43
// System.out.print(processOpera.getProcessEarliestBeginTime(
44
// processOpera.process[i].startNode,
45
// processOpera.process[i].endNode)
46
// + " ");
47
// System.out.print(processOpera
48
// .getItemLatestEndTime(processOpera.process[i].startNode)
49
// + " ");
50
// System.out.print(processOpera.getProcessLatestBeginTime(
51
// processOpera.process[i].startNode,
52
// processOpera.process[i].endNode)
53
// + " ");
54
// System.out.print(processOpera.getProcessLatestEndTime(
55
// processOpera.process[i].startNode,
56
// processOpera.process[i].endNode)
57
// + " ");
58
// System.out.print(processOpera.getProcessIntervalTime(
59
// processOpera.process[i].startNode,
60
// processOpera.process[i].endNode)
61
// + " ");
62
// System.out.print(processOpera.getKeyPath(
63
// processOpera.process[i].startNode,
64
// processOpera.process[i].endNode)
65
// + " ");
66
// System.out.println();
67
// }
68
//
69
// System.out.println(processOpera.getItemEarliestBeginTime(1));
70
processOpera.searchProcess(2, 8, 0);
71
processOpera.showPath();
72
}
73
74
/**
75
* 初始化所有路径信息,放进数组中
76
*/
77
public void setup()
78
{
79
addProcessInfo(1, 2, 60);
80
addProcessInfo(2, 3, 10);
81
addProcessInfo(2, 4, 20);
82
addProcessInfo(2, 5, 40);
83
addProcessInfo(2, 7, 45);
84
addProcessInfo(3, 7, 18);
85
addProcessInfo(4, 5, 0);
86
addProcessInfo(4, 6, 30);
87
addProcessInfo(5, 7, 15);
88
addProcessInfo(6, 7, 25);
89
addProcessInfo(7, 8, 35);
90
addProcessInfo(8, 8, 0);
91
}
92
93
/**
94
* 增加路径信息到数组中
95
*
96
* @param sNode
97
* 开始节点
98
* @param eNode
99
* 终止节点
100
* @param lTime
101
* 持续时间
102
*/
103
public void addProcessInfo(int sNode, int eNode, int lTime)
104
{
105
if (numProcess < MAX) // 如果数组没满的话
106
{
107
process[numProcess] = new ProcessInfo(sNode, eNode, lTime);
108
numProcess++;
109
}
110
else
111
{
112
System.out
113
.println("ProcessInfo database full!\nAdd error,program exit!");
114
System.exit(0);
115
}
116
}
117
118
/**
119
* 给所有路径信息中的附加属性赋值,要完成的话,需要遍历路径数组中的所有元素。 对于每个元素,要查看数组中的其它元素,确立关系
120
*/
121
public void setNodeTag()
122
{
123
for (int i = 0; i < numProcess; i++) // 遍历路径数组中的所有元素,process[i]是选取的路径
124
{
125
for (int j = 0; j < numProcess; j++) // 查看其它元素
126
{
127
if (i == j) continue; // 自己比自己,没得比,继续下次循环
128
// 发现有路径可以和选取路径连接
129
if (process[j].endNode == process[i].startNode)
130
{
131
process[i].hasFrontNode = true;
132
}
133
// 两条不同路径的终结点一样
134
if (process[j].endNode == process[i].endNode)
135
{
136
process[i].eNodeIsBranchEndNode = true;
137
}
138
// 两条不同路径的起始点一样
139
if (process[j].startNode == process[i].startNode)
140
{
141
process[i].sNodeIsBranchBeginNode = true;
142
}
143
}
144
}
145
}
146
147
/**
148
* 找出以选取点为终结点的没走过的一条路径
149
*
150
* @param eNode
151
* 所选取的点
152
* @return 没被走过的以选取点为终结点的一条路径
153
*/
154
public ProcessInfo findProcessInfo(int eNode)
155
{
156
for (int i = 0; i < numProcess; i++) // 遍历路径信息
157
{
158
// process[i].skip=false 路径才没被走过
159
if ((process[i].endNode == eNode) && (!process[i].skip))
160
{
161
// 由于深度复制和浅度复制的问题,所以复制的时候要新建一个ProcessInfo,而不是引用原来
162
// 这是实现问题,算法与此可以无关
163
ProcessInfo pInfo = new ProcessInfo(process[i].startNode,
164
process[i].endNode, process[i].lastingTime);
165
process[i].skip = true;
166
pInfo.hasFrontNode = process[i].hasFrontNode;
167
pInfo.eNodeIsBranchEndNode = process[i].eNodeIsBranchEndNode;
168
return pInfo;
169
}
170
}
171
return null; // 没有合适的路径就返回null了
172
}
173
174
/**
175
* 核心部分所在,查找任意2点间最长路径 基于AI设计,简单的AI 理论上来说,顺着找和倒着找是一样的,由于项目原因,这里我是倒着找的
176
* 查找到的路径放在结果栈resultStack中
177
*
178
* @param sNode
179
* 开始节点
180
* @param eNode
181
* 终止节点
182
* @param depth
183
* 显示debug信息的时候用到,用于显示层次关系
184
*/
185
public void searchProcess(int sNode, int eNode, int depth)
186
{
187
// 变量定义尽量少放循环中,故先定义
188
int lastingTime; // 持续时间
189
ProcessInfo pInfo; // 保存路径信息的对象
190
int numStartNode = 0; // 查找起点的个数
191
Stack resultTemp; // 保存查找到路径的临时栈
192
while ((pInfo = findProcessInfo(eNode)) != null)
193
{
194
// 分支节点数目+1
195
numStartNode++;
196
// 将查找到的路径信息放到分支节点栈,然后再查
197
branchProcessStack.push(pInfo);
198
showDebugInfo("分支路径栈加入:" + pInfo.startNode + "-->" + pInfo.endNode,
199
depth);
200
}
201
if (numStartNode > 0) // 有分支的话,如果这里不成立,整个就结束了
202
{
203
for (int i = 0; i < numStartNode; i++) // 遍历分支节点栈
204
{
205
pInfo = (ProcessInfo) branchProcessStack.pop(); // 获得一条分支路径
206
showDebugInfo("分支路径栈弹出:" + pInfo.startNode + "-->"
207
+ pInfo.endNode, depth);
208
// 为了防止头尾一样的路径,有了下面的判断,理论上是没有,但实际会出现
209
if (pInfo.startNode == pInfo.endNode)
210
{
211
showDebugInfo("头尾节点一样,丢弃!", depth + 1);
212
continue;
213
}
214
215
// 如果存在可到达的路径的话,注意,这是个递归过程
216
if (pInfo.startNode == sNode)
217
{
218
// 当前路径加入回退栈,此时,回退栈里可以找出一条完整的路径了
219
backTrackStack.push(pInfo);
220
showDebugInfo("--------到达起点:" + pInfo.startNode + "-->"
221
+ pInfo.endNode + "--------", depth);
222
int numbackTrackStack = backTrackStack.size();
223
resultTemp = new Stack();
224
lastingTime = 0;
225
for (int j = 0; j < numbackTrackStack; j++)
226
{
227
pInfo = (ProcessInfo) backTrackStack.get(j);
228
showDebugInfo("回溯栈内容进入临时结果栈:" + pInfo.startNode + "-->"
229
+ pInfo.endNode, depth);
230
lastingTime += pInfo.lastingTime;
231
resultTemp.push(pInfo);
232
}
233
// 判断是不是更好的解
234
if (lastingTime > maxLastingTime)
235
{
236
showDebugInfo("========找到更优解!========", depth);
237
maxLastingTime = lastingTime;
238
resultStack = resultTemp;
239
}
240
// 找出一条后,需要回退,然后继续找下一条
241
// 获得剩余分支路径的数目
242
int numBranch = branchProcessStack.size();
243
244
if (numBranch == 0)
245
{
246
// 没分支路径了,查找结束,清空回退栈
247
backTrackStack.removeAllElements();
248
}
249
else if (numBranch > 0)
250
{
251
int index = numBranch - 1;
252
int backTrackValue = ((ProcessInfo) branchProcessStack
253
.get(index)).endNode;
254
showDebugInfo("--------回退到节点:" + backTrackValue
255
+ "--------", depth);
256
// 要回退到的节点必是分支路径栈中最上路径的尾节点
257
// 下面的循环就是一直回退,由于还有分支路径,所以可以找到要退到的点
258
do
259
{
260
pInfo = (ProcessInfo) backTrackStack.pop();
261
showDebugInfo("找到目标,回溯栈回退到:" + pInfo.startNode
262
+ "-->" + pInfo.endNode, depth);
263
}
264
while (pInfo.endNode != backTrackValue);
265
}
266
// 回退后,继续查找的话,所有路径的经过标记都要重置,否则经过了的路径是不会再去查的
267
// 由于开始路径不同,所以不会找到同样的结果
268
resetAllSkip();
269
continue;// 开始从下个分支路径查找
270
}
271
else
272
// 没有直接从sNode到eNode的工序
273
{
274
// 还没到目标
275
// 如果当前路径的起点还有前驱节点的话,需要递归查找,这是重点
276
if (pInfo.hasFrontNode)
277
{
278
ProcessInfo btPInfo = new ProcessInfo(sNode, eNode,
279
pInfo.lastingTime);
280
btPInfo.eNodeIsBranchEndNode = pInfo.eNodeIsBranchEndNode;
281
// 说明找过sNode-->eNode
282
backTrackStack.push(btPInfo);
283
showDebugInfo("回溯栈加入:" + sNode + "-->" + eNode
284
+ ",说明找过" + sNode + "-->" + eNode, depth + 1);
285
showDebugInfo("查找:" + sNode + "-->" + pInfo.startNode,
286
depth + 1);
287
searchProcess(sNode, pInfo.startNode, depth + 2);
288
}
289
else
290
// 当前路径的起点无前驱,则路径错误,需要回溯
291
{
292
// 如果当前路径的终结点还有其它前驱的话,则退出本次循环,从下个分支路径查找
293
if (pInfo.eNodeIsBranchEndNode)
294
{
295
continue;
296
}
297
// 如果当前路径的终结点没有其它前驱,就要回退了
298
else if (backTrackStack.size() > 0)
299
{
300
// 开始回退,一直到找到个路径的终止节点有多个前驱为止,或者是回退栈已经空了。
301
do
302
{
303
pInfo = (ProcessInfo) backTrackStack.pop();
304
showDebugInfo("路径错误,开始回溯,回溯栈弹出:"
305
+ pInfo.startNode + "-->"
306
+ pInfo.endNode, depth + 1);
307
}
308
while ((!pInfo.eNodeIsBranchEndNode)
309
&& (backTrackStack.size() > 0));
310
}
311
}
312
}
313
}
314
showDebugInfo("分支已被找遍", depth);
315
}
316
else
317
{
318
showDebugInfo("前面已走过这条路径且被证明走不通,或尾节点没有前驱节点", depth);
319
if (backTrackStack.size()>0)
320
{
321
pInfo = (ProcessInfo) backTrackStack.pop();
322
showDebugInfo("路径不通,回溯栈弹出:" + pInfo.startNode + "-->"
323
+ pInfo.endNode, depth - 1);
324
if (branchProcessStack.size()>0)
325
{
326
int fixNode = ((ProcessInfo) branchProcessStack.lastElement()).endNode;
327
if (fixNode != pInfo.endNode)
328
{
329
showDebugInfo("========需要调整回溯栈========", depth);
330
showDebugInfo("========开始调整回溯栈========", depth);
331
do
332
{
333
pInfo = (ProcessInfo) backTrackStack.pop();
334
showDebugInfo("回溯栈弹出:" + pInfo.startNode + "-->"
335
+ pInfo.endNode, depth + 1);
336
}
337
while (fixNode != pInfo.endNode);
338
showDebugInfo("========回溯栈调整结束========", depth);
339
}
340
}
341
}
342
}
343
}
344
345
private void showDebugInfo(String info, int blankCount)
346
{
347
String blank = "";
348
for (int i = 0; i < blankCount; i++)
349
{
350
blank += " ";
351
}
352
System.out.println(blank + info);
353
}
354
355
public int getLastingTime(int sNode, int eNode)
356
{
357
int lastingTime = 0;
358
ProcessInfo pInfo;
359
searchProcess(sNode, eNode, 0);
360
int num = resultStack.size();
361
for (int i = num - 1; i >= 0; i--)
362
{
363
pInfo = (ProcessInfo) resultStack.get(i);
364
lastingTime += pInfo.lastingTime;
365
}
366
return lastingTime;
367
}
368
369
public void showPath()
370
{
371
ProcessInfo pInfo;
372
int num = resultStack.size();
373
if (num==0)
374
{
375
showDebugInfo("========没有符合要求的路径========",0);
376
}
377
else
378
{
379
for (int i = 0; i < num; i++)
380
{
381
pInfo = (ProcessInfo) resultStack.pop();
382
System.out.print("-->" + pInfo.endNode);
383
}
384
}
385
}
386
387
public void resetAllSkip()
388
{
389
for (int i = 0; i < numProcess; i++)
390
{
391
process[i].skip = false;
392
}
393
}
394
395
public int getItemEarliestBeginTime(int itemIndex)
396
{
397
maxLastingTime = 0;
398
backTrackStack.removeAllElements();
399
resultStack.removeAllElements();
400
return getLastingTime(1, itemIndex);
401
}
402
403
public int getProcessEarliestEndTime(int sNode, int eNode)
404
{
405
for (int i = 0; i < numProcess; i++)
406
{
407
if ((process[i].startNode == sNode)
408
&& (process[i].endNode == eNode))
409
{
410
return (getItemEarliestBeginTime(sNode) + process[i].lastingTime);
411
}
412
}
413
return 0;
414
}
415
416
public int getProcessEarliestBeginTime(int sNode, int eNode)
417
{
418
return (getItemEarliestBeginTime(sNode));
419
}
420
421
public int getItemLatestEndTime(int itemIndex)
422
{
423
int maxTime = 0;
424
int t = 0;
425
int pos = -1;
426
boolean hasNextNode = false;
427
backTrackStack.removeAllElements();
428
resultStack.removeAllElements();
429
for (int i = 0; i < numProcess; i++)
430
{
431
if (process[i].startNode == itemIndex)
432
{
433
if (process[i].sNodeIsBranchBeginNode)
434
{
435
return (getItemEarliestBeginTime(itemIndex));
436
}
437
hasNextNode = true;
438
t = getItemEarliestBeginTime(process[i].endNode);
439
if (t > maxTime)
440
{
441
pos = i;
442
maxTime = t;
443
}
444
}
445
}
446
if (!hasNextNode)
447
{
448
return (getItemEarliestBeginTime(itemIndex));
449
}
450
else
451
{
452
return (t - process[pos].lastingTime);
453
}
454
}
455
456
public int getProcessLatestEndTime(int sNode, int eNode)
457
{
458
return (getItemLatestEndTime(eNode));
459
}
460
461
public int getProcessLatestBeginTime(int sNode, int eNode)
462
{
463
for (int i = 0; i < numProcess; i++)
464
{
465
if ((process[i].startNode == sNode)
466
&& (process[i].endNode == eNode))
467
{
468
return (getProcessLatestEndTime(sNode, eNode) - process[i].lastingTime);
469
}
470
}
471
return 0;
472
}
473
474
public int getProcessIntervalTime(int sNode, int eNode)
475
{
476
return (getProcessLatestEndTime(sNode, eNode) - getProcessEarliestEndTime(
477
sNode, eNode));
478
}
479
480
public int getKeyPath(int sNode, int eNode)
481
{
482
if ((getProcessIntervalTime(sNode, eNode) == 0) && (sNode != eNode))
483
{
484
return eNode;
485
}
486
else
487
{
488
return 0;
489
}
490
}
491
}
最后是调试信息(找2到8):
import java.util.Stack;2

3
/**4
* @author zxub Created on 2005-5-22 10:19:515
*/6
public class ProcessOpera7
{8

9
final int MAX = 100;10
// 保存路径信息的数组11
ProcessInfo process[] = new ProcessInfo[MAX];12
// 保存路径数目13
int numProcess = 0;14
// 分支路径栈15
Stack branchProcessStack = new Stack();16
// 用于搜索回退的栈17
Stack backTrackStack = new Stack();18
// 保存最后结果的栈19
Stack resultStack = new Stack();20
// 最长持续时间21
int maxLastingTime = 0;22

23
/**24
* 测试用25
* 26
* @param args27
*/28
public static void main(String[] args)29
{30

31
ProcessOpera processOpera = new ProcessOpera();32
processOpera.setup();33
processOpera.setNodeTag();34
// for (int i = 0; i < processOpera.numProcess; i++)35
// {36
// System.out.print(processOpera37
// .getItemEarliestBeginTime(processOpera.process[i].startNode)38
// + " ");39
// System.out.print(processOpera.getProcessEarliestEndTime(40
// processOpera.process[i].startNode,41
// processOpera.process[i].endNode)42
// + " ");43
// System.out.print(processOpera.getProcessEarliestBeginTime(44
// processOpera.process[i].startNode,45
// processOpera.process[i].endNode)46
// + " ");47
// System.out.print(processOpera48
// .getItemLatestEndTime(processOpera.process[i].startNode)49
// + " ");50
// System.out.print(processOpera.getProcessLatestBeginTime(51
// processOpera.process[i].startNode,52
// processOpera.process[i].endNode)53
// + " ");54
// System.out.print(processOpera.getProcessLatestEndTime(55
// processOpera.process[i].startNode,56
// processOpera.process[i].endNode)57
// + " ");58
// System.out.print(processOpera.getProcessIntervalTime(59
// processOpera.process[i].startNode,60
// processOpera.process[i].endNode)61
// + " ");62
// System.out.print(processOpera.getKeyPath(63
// processOpera.process[i].startNode,64
// processOpera.process[i].endNode)65
// + " ");66
// System.out.println();67
// }68
// 69
// System.out.println(processOpera.getItemEarliestBeginTime(1));70
processOpera.searchProcess(2, 8, 0);71
processOpera.showPath();72
}73

74
/**75
* 初始化所有路径信息,放进数组中76
*/77
public void setup()78
{79
addProcessInfo(1, 2, 60);80
addProcessInfo(2, 3, 10);81
addProcessInfo(2, 4, 20);82
addProcessInfo(2, 5, 40);83
addProcessInfo(2, 7, 45);84
addProcessInfo(3, 7, 18);85
addProcessInfo(4, 5, 0);86
addProcessInfo(4, 6, 30);87
addProcessInfo(5, 7, 15);88
addProcessInfo(6, 7, 25);89
addProcessInfo(7, 8, 35);90
addProcessInfo(8, 8, 0);91
}92

93
/**94
* 增加路径信息到数组中95
* 96
* @param sNode97
* 开始节点98
* @param eNode99
* 终止节点100
* @param lTime101
* 持续时间102
*/103
public void addProcessInfo(int sNode, int eNode, int lTime)104
{105
if (numProcess < MAX) // 如果数组没满的话106
{107
process[numProcess] = new ProcessInfo(sNode, eNode, lTime);108
numProcess++;109
}110
else111
{112
System.out113
.println("ProcessInfo database full!\nAdd error,program exit!");114
System.exit(0);115
}116
}117

118
/**119
* 给所有路径信息中的附加属性赋值,要完成的话,需要遍历路径数组中的所有元素。 对于每个元素,要查看数组中的其它元素,确立关系120
*/121
public void setNodeTag()122
{123
for (int i = 0; i < numProcess; i++) // 遍历路径数组中的所有元素,process[i]是选取的路径124
{125
for (int j = 0; j < numProcess; j++) // 查看其它元素126
{127
if (i == j) continue; // 自己比自己,没得比,继续下次循环128
// 发现有路径可以和选取路径连接129
if (process[j].endNode == process[i].startNode)130
{131
process[i].hasFrontNode = true;132
}133
// 两条不同路径的终结点一样134
if (process[j].endNode == process[i].endNode)135
{136
process[i].eNodeIsBranchEndNode = true;137
}138
// 两条不同路径的起始点一样139
if (process[j].startNode == process[i].startNode)140
{141
process[i].sNodeIsBranchBeginNode = true;142
}143
}144
}145
}146

147
/**148
* 找出以选取点为终结点的没走过的一条路径149
* 150
* @param eNode151
* 所选取的点152
* @return 没被走过的以选取点为终结点的一条路径153
*/154
public ProcessInfo findProcessInfo(int eNode)155
{156
for (int i = 0; i < numProcess; i++) // 遍历路径信息157
{158
// process[i].skip=false 路径才没被走过159
if ((process[i].endNode == eNode) && (!process[i].skip))160
{161
// 由于深度复制和浅度复制的问题,所以复制的时候要新建一个ProcessInfo,而不是引用原来162
// 这是实现问题,算法与此可以无关163
ProcessInfo pInfo = new ProcessInfo(process[i].startNode,164
process[i].endNode, process[i].lastingTime);165
process[i].skip = true;166
pInfo.hasFrontNode = process[i].hasFrontNode;167
pInfo.eNodeIsBranchEndNode = process[i].eNodeIsBranchEndNode;168
return pInfo;169
}170
}171
return null; // 没有合适的路径就返回null了172
}173

174
/**175
* 核心部分所在,查找任意2点间最长路径 基于AI设计,简单的AI 理论上来说,顺着找和倒着找是一样的,由于项目原因,这里我是倒着找的176
* 查找到的路径放在结果栈resultStack中177
* 178
* @param sNode179
* 开始节点180
* @param eNode181
* 终止节点182
* @param depth183
* 显示debug信息的时候用到,用于显示层次关系184
*/185
public void searchProcess(int sNode, int eNode, int depth)186
{187
// 变量定义尽量少放循环中,故先定义188
int lastingTime; // 持续时间189
ProcessInfo pInfo; // 保存路径信息的对象190
int numStartNode = 0; // 查找起点的个数191
Stack resultTemp; // 保存查找到路径的临时栈192
while ((pInfo = findProcessInfo(eNode)) != null)193
{194
// 分支节点数目+1195
numStartNode++;196
// 将查找到的路径信息放到分支节点栈,然后再查197
branchProcessStack.push(pInfo);198
showDebugInfo("分支路径栈加入:" + pInfo.startNode + "-->" + pInfo.endNode,199
depth);200
}201
if (numStartNode > 0) // 有分支的话,如果这里不成立,整个就结束了202
{203
for (int i = 0; i < numStartNode; i++) // 遍历分支节点栈204
{205
pInfo = (ProcessInfo) branchProcessStack.pop(); // 获得一条分支路径206
showDebugInfo("分支路径栈弹出:" + pInfo.startNode + "-->"207
+ pInfo.endNode, depth);208
// 为了防止头尾一样的路径,有了下面的判断,理论上是没有,但实际会出现209
if (pInfo.startNode == pInfo.endNode)210
{211
showDebugInfo("头尾节点一样,丢弃!", depth + 1);212
continue;213
}214

215
// 如果存在可到达的路径的话,注意,这是个递归过程216
if (pInfo.startNode == sNode)217
{218
// 当前路径加入回退栈,此时,回退栈里可以找出一条完整的路径了219
backTrackStack.push(pInfo);220
showDebugInfo("--------到达起点:" + pInfo.startNode + "-->"221
+ pInfo.endNode + "--------", depth);222
int numbackTrackStack = backTrackStack.size();223
resultTemp = new Stack();224
lastingTime = 0;225
for (int j = 0; j < numbackTrackStack; j++)226
{227
pInfo = (ProcessInfo) backTrackStack.get(j);228
showDebugInfo("回溯栈内容进入临时结果栈:" + pInfo.startNode + "-->"229
+ pInfo.endNode, depth);230
lastingTime += pInfo.lastingTime;231
resultTemp.push(pInfo);232
}233
// 判断是不是更好的解234
if (lastingTime > maxLastingTime)235
{236
showDebugInfo("========找到更优解!========", depth);237
maxLastingTime = lastingTime;238
resultStack = resultTemp;239
}240
// 找出一条后,需要回退,然后继续找下一条241
// 获得剩余分支路径的数目242
int numBranch = branchProcessStack.size();243

244
if (numBranch == 0)245
{246
// 没分支路径了,查找结束,清空回退栈247
backTrackStack.removeAllElements();248
}249
else if (numBranch > 0)250
{251
int index = numBranch - 1;252
int backTrackValue = ((ProcessInfo) branchProcessStack253
.get(index)).endNode;254
showDebugInfo("--------回退到节点:" + backTrackValue255
+ "--------", depth);256
// 要回退到的节点必是分支路径栈中最上路径的尾节点257
// 下面的循环就是一直回退,由于还有分支路径,所以可以找到要退到的点258
do259
{260
pInfo = (ProcessInfo) backTrackStack.pop();261
showDebugInfo("找到目标,回溯栈回退到:" + pInfo.startNode262
+ "-->" + pInfo.endNode, depth);263
}264
while (pInfo.endNode != backTrackValue);265
}266
// 回退后,继续查找的话,所有路径的经过标记都要重置,否则经过了的路径是不会再去查的267
// 由于开始路径不同,所以不会找到同样的结果268
resetAllSkip();269
continue;// 开始从下个分支路径查找270
}271
else272
// 没有直接从sNode到eNode的工序273
{274
// 还没到目标275
// 如果当前路径的起点还有前驱节点的话,需要递归查找,这是重点276
if (pInfo.hasFrontNode)277
{278
ProcessInfo btPInfo = new ProcessInfo(sNode, eNode,279
pInfo.lastingTime);280
btPInfo.eNodeIsBranchEndNode = pInfo.eNodeIsBranchEndNode;281
// 说明找过sNode-->eNode282
backTrackStack.push(btPInfo);283
showDebugInfo("回溯栈加入:" + sNode + "-->" + eNode284
+ ",说明找过" + sNode + "-->" + eNode, depth + 1);285
showDebugInfo("查找:" + sNode + "-->" + pInfo.startNode,286
depth + 1);287
searchProcess(sNode, pInfo.startNode, depth + 2);288
}289
else290
// 当前路径的起点无前驱,则路径错误,需要回溯291
{292
// 如果当前路径的终结点还有其它前驱的话,则退出本次循环,从下个分支路径查找293
if (pInfo.eNodeIsBranchEndNode)294
{295
continue;296
}297
// 如果当前路径的终结点没有其它前驱,就要回退了298
else if (backTrackStack.size() > 0)299
{300
// 开始回退,一直到找到个路径的终止节点有多个前驱为止,或者是回退栈已经空了。301
do302
{303
pInfo = (ProcessInfo) backTrackStack.pop();304
showDebugInfo("路径错误,开始回溯,回溯栈弹出:"305
+ pInfo.startNode + "-->"306
+ pInfo.endNode, depth + 1);307
}308
while ((!pInfo.eNodeIsBranchEndNode)309
&& (backTrackStack.size() > 0));310
}311
}312
}313
}314
showDebugInfo("分支已被找遍", depth);315
}316
else317
{318
showDebugInfo("前面已走过这条路径且被证明走不通,或尾节点没有前驱节点", depth);319
if (backTrackStack.size()>0)320
{321
pInfo = (ProcessInfo) backTrackStack.pop();322
showDebugInfo("路径不通,回溯栈弹出:" + pInfo.startNode + "-->"323
+ pInfo.endNode, depth - 1);324
if (branchProcessStack.size()>0)325
{326
int fixNode = ((ProcessInfo) branchProcessStack.lastElement()).endNode; 327
if (fixNode != pInfo.endNode)328
{329
showDebugInfo("========需要调整回溯栈========", depth);330
showDebugInfo("========开始调整回溯栈========", depth);331
do332
{333
pInfo = (ProcessInfo) backTrackStack.pop();334
showDebugInfo("回溯栈弹出:" + pInfo.startNode + "-->"335
+ pInfo.endNode, depth + 1);336
}337
while (fixNode != pInfo.endNode);338
showDebugInfo("========回溯栈调整结束========", depth);339
}340
}341
} 342
}343
}344
345
private void showDebugInfo(String info, int blankCount)346
{347
String blank = "";348
for (int i = 0; i < blankCount; i++)349
{350
blank += " ";351
}352
System.out.println(blank + info);353
}354

355
public int getLastingTime(int sNode, int eNode)356
{357
int lastingTime = 0;358
ProcessInfo pInfo;359
searchProcess(sNode, eNode, 0);360
int num = resultStack.size();361
for (int i = num - 1; i >= 0; i--)362
{363
pInfo = (ProcessInfo) resultStack.get(i);364
lastingTime += pInfo.lastingTime;365
}366
return lastingTime;367
}368

369
public void showPath()370
{371
ProcessInfo pInfo;372
int num = resultStack.size();373
if (num==0)374
{375
showDebugInfo("========没有符合要求的路径========",0);376
}377
else378
{379
for (int i = 0; i < num; i++)380
{381
pInfo = (ProcessInfo) resultStack.pop();382
System.out.print("-->" + pInfo.endNode);383
}384
} 385
}386

387
public void resetAllSkip()388
{389
for (int i = 0; i < numProcess; i++)390
{391
process[i].skip = false;392
}393
}394

395
public int getItemEarliestBeginTime(int itemIndex)396
{397
maxLastingTime = 0;398
backTrackStack.removeAllElements();399
resultStack.removeAllElements();400
return getLastingTime(1, itemIndex);401
}402

403
public int getProcessEarliestEndTime(int sNode, int eNode)404
{405
for (int i = 0; i < numProcess; i++)406
{407
if ((process[i].startNode == sNode)408
&& (process[i].endNode == eNode))409
{410
return (getItemEarliestBeginTime(sNode) + process[i].lastingTime);411
}412
}413
return 0;414
}415

416
public int getProcessEarliestBeginTime(int sNode, int eNode)417
{418
return (getItemEarliestBeginTime(sNode));419
}420

421
public int getItemLatestEndTime(int itemIndex)422
{423
int maxTime = 0;424
int t = 0;425
int pos = -1;426
boolean hasNextNode = false;427
backTrackStack.removeAllElements();428
resultStack.removeAllElements();429
for (int i = 0; i < numProcess; i++)430
{431
if (process[i].startNode == itemIndex)432
{433
if (process[i].sNodeIsBranchBeginNode)434
{435
return (getItemEarliestBeginTime(itemIndex));436
}437
hasNextNode = true;438
t = getItemEarliestBeginTime(process[i].endNode);439
if (t > maxTime)440
{441
pos = i;442
maxTime = t;443
}444
}445
}446
if (!hasNextNode)447
{448
return (getItemEarliestBeginTime(itemIndex));449
}450
else451
{452
return (t - process[pos].lastingTime);453
}454
}455

456
public int getProcessLatestEndTime(int sNode, int eNode)457
{458
return (getItemLatestEndTime(eNode));459
}460

461
public int getProcessLatestBeginTime(int sNode, int eNode)462
{463
for (int i = 0; i < numProcess; i++)464
{465
if ((process[i].startNode == sNode)466
&& (process[i].endNode == eNode))467
{468
return (getProcessLatestEndTime(sNode, eNode) - process[i].lastingTime);469
}470
}471
return 0;472
}473

474
public int getProcessIntervalTime(int sNode, int eNode)475
{476
return (getProcessLatestEndTime(sNode, eNode) - getProcessEarliestEndTime(477
sNode, eNode));478
}479

480
public int getKeyPath(int sNode, int eNode)481
{482
if ((getProcessIntervalTime(sNode, eNode) == 0) && (sNode != eNode))483
{484
return eNode;485
}486
else487
{488
return 0;489
}490
} 491
}
分支路径栈加入:7-->8
分支路径栈加入:8-->8
分支路径栈弹出:8-->8
头尾节点一样,丢弃!
分支路径栈弹出:7-->8
回溯栈加入:2-->8,说明找过2-->8
查找:2-->7
分支路径栈加入:2-->7
分支路径栈加入:3-->7
分支路径栈加入:5-->7
分支路径栈加入:6-->7
分支路径栈弹出:6-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->6
分支路径栈加入:4-->6
分支路径栈弹出:4-->6
回溯栈加入:2-->6,说明找过2-->6
查找:2-->4
分支路径栈加入:2-->4
分支路径栈弹出:2-->4
--------到达起点:2-->4--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->6
回溯栈内容进入临时结果栈:2-->4
========找到更优解!========
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->4
找到目标,回溯栈回退到:2-->6
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支已被找遍
分支路径栈弹出:5-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->5
分支路径栈加入:2-->5
分支路径栈加入:4-->5
分支路径栈弹出:4-->5
回溯栈加入:2-->5,说明找过2-->5
查找:2-->4
分支路径栈加入:2-->4
分支路径栈弹出:2-->4
--------到达起点:2-->4--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->5
回溯栈内容进入临时结果栈:2-->4
--------回退到节点:5--------
找到目标,回溯栈回退到:2-->4
找到目标,回溯栈回退到:2-->5
分支已被找遍
分支路径栈弹出:2-->5
--------到达起点:2-->5--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->5
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->5
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支路径栈弹出:3-->7
回溯栈加入:2-->7,说明找过2-->7
查找:2-->3
分支路径栈加入:2-->3
分支路径栈弹出:2-->3
--------到达起点:2-->3--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
回溯栈内容进入临时结果栈:2-->3
--------回退到节点:7--------
找到目标,回溯栈回退到:2-->3
找到目标,回溯栈回退到:2-->7
分支已被找遍
分支路径栈弹出:2-->7
--------到达起点:2-->7--------
回溯栈内容进入临时结果栈:2-->8
回溯栈内容进入临时结果栈:2-->7
分支已被找遍
分支已被找遍
-->4-->6-->7-->8 1
分支路径栈加入:2-->7
2
分支路径栈加入:3-->7
3
分支路径栈加入:5-->7
4
分支路径栈加入:6-->7
5
分支路径栈弹出:6-->7
6
回溯栈加入:3-->7,说明找过3-->7
7
查找:3-->6
8
分支路径栈加入:4-->6
9
分支路径栈弹出:4-->6
10
回溯栈加入:3-->6,说明找过3-->6
11
查找:3-->4
12
分支路径栈加入:2-->4
13
分支路径栈弹出:2-->4
14
回溯栈加入:3-->4,说明找过3-->4
15
查找:3-->2
16
分支路径栈加入:1-->2
17
分支路径栈弹出:1-->2
18
路径错误,开始回溯,回溯栈弹出:3-->4
19
路径错误,开始回溯,回溯栈弹出:3-->6
20
路径错误,开始回溯,回溯栈弹出:3-->7
21
分支已被找遍
22
分支已被找遍
23
分支已被找遍
24
分支路径栈弹出:5-->7
25
回溯栈加入:3-->7,说明找过3-->7
26
查找:3-->5
27
分支路径栈加入:2-->5
28
分支路径栈加入:4-->5
29
分支路径栈弹出:4-->5
30
回溯栈加入:3-->5,说明找过3-->5
31
查找:3-->4
32
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点
33
路径不通,回溯栈弹出:3-->5
34
分支路径栈弹出:2-->5
35
回溯栈加入:3-->5,说明找过3-->5
36
查找:3-->2
37
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点
38
路径不通,回溯栈弹出:3-->5
39
========需要调整回溯栈========
40
========开始调整回溯栈========
41
回溯栈弹出:3-->7
42
========回溯栈调整结束========
43
分支已被找遍
44
分支路径栈弹出:3-->7
45
--------到达起点:3-->7--------
46
回溯栈内容进入临时结果栈:3-->7
47
========找到更优解!========
48
--------回退到节点:7--------
49
找到目标,回溯栈回退到:3-->7
50
分支路径栈弹出:2-->7
51
回溯栈加入:3-->7,说明找过3-->7
52
查找:3-->2
53
分支路径栈加入:1-->2
54
分支路径栈弹出:1-->2
55
路径错误,开始回溯,回溯栈弹出:3-->7
56
分支已被找遍
57
分支已被找遍
58
-->7
先写到这里,以后再来修改。
分支路径栈加入:2-->72
分支路径栈加入:3-->73
分支路径栈加入:5-->74
分支路径栈加入:6-->75
分支路径栈弹出:6-->76
回溯栈加入:3-->7,说明找过3-->77
查找:3-->68
分支路径栈加入:4-->69
分支路径栈弹出:4-->610
回溯栈加入:3-->6,说明找过3-->611
查找:3-->412
分支路径栈加入:2-->413
分支路径栈弹出:2-->414
回溯栈加入:3-->4,说明找过3-->415
查找:3-->216
分支路径栈加入:1-->217
分支路径栈弹出:1-->218
路径错误,开始回溯,回溯栈弹出:3-->419
路径错误,开始回溯,回溯栈弹出:3-->620
路径错误,开始回溯,回溯栈弹出:3-->721
分支已被找遍22
分支已被找遍23
分支已被找遍24
分支路径栈弹出:5-->725
回溯栈加入:3-->7,说明找过3-->726
查找:3-->527
分支路径栈加入:2-->528
分支路径栈加入:4-->529
分支路径栈弹出:4-->530
回溯栈加入:3-->5,说明找过3-->531
查找:3-->432
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点33
路径不通,回溯栈弹出:3-->534
分支路径栈弹出:2-->535
回溯栈加入:3-->5,说明找过3-->536
查找:3-->237
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点38
路径不通,回溯栈弹出:3-->539
========需要调整回溯栈========40
========开始调整回溯栈========41
回溯栈弹出:3-->742
========回溯栈调整结束========43
分支已被找遍44
分支路径栈弹出:3-->745
--------到达起点:3-->7--------46
回溯栈内容进入临时结果栈:3-->747
========找到更优解!========48
--------回退到节点:7--------49
找到目标,回溯栈回退到:3-->750
分支路径栈弹出:2-->751
回溯栈加入:3-->7,说明找过3-->752
查找:3-->253
分支路径栈加入:1-->254
分支路径栈弹出:1-->255
路径错误,开始回溯,回溯栈弹出:3-->756
分支已被找遍57
分支已被找遍58
-->7


posted on
浙公网安备 33010602011771号